mirror of
https://github.com/Karaka-Management/oms-QA.git
synced 2026-01-11 15:48:42 +00:00
create draft
This commit is contained in:
parent
24d2494c6e
commit
356237d0f8
|
|
@ -42,6 +42,7 @@ use phpOMS\Message\RequestAbstract;
|
|||
use phpOMS\Message\ResponseAbstract;
|
||||
use phpOMS\Model\Message\FormValidation;
|
||||
use phpOMS\Utils\Parser\Markdown\Markdown;
|
||||
use Modules\Profile\Models\Profile;
|
||||
|
||||
/**
|
||||
* Task class.
|
||||
|
|
@ -153,7 +154,7 @@ final class ApiController extends Controller
|
|||
$question->setLanguage((string) $request->getData('language'));
|
||||
$question->setCategory(new NullQACategory((int) $request->getData('category')));
|
||||
$question->setStatus((int) $request->getData('status'));
|
||||
$question->createdBy = new NullAccount($request->header->account);
|
||||
$question->createdBy = new Profile(new NullAccount($request->header->account));
|
||||
|
||||
if (!empty($tags = $request->getDataJson('tags'))) {
|
||||
foreach ($tags as $tag) {
|
||||
|
|
@ -246,7 +247,7 @@ final class ApiController extends Controller
|
|||
$answer->answerRaw = (string) $request->getData('plain');
|
||||
$answer->answer = Markdown::parse((string) ($request->getData('plain') ?? ''));
|
||||
$answer->question = new NullQAQuestion((int) $request->getData('question'));
|
||||
$answer->isAccepted = (bool) ($request->getData('accepted') ?? false);
|
||||
$answer->isAccepted = false;
|
||||
$answer->setStatus((int) $request->getData('status'));
|
||||
$answer->createdBy = new NullAccount($request->header->account);
|
||||
|
||||
|
|
@ -278,6 +279,44 @@ final class ApiController extends Controller
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to create a answer
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
* @param ResponseAbstract $response Response
|
||||
* @param mixed $data Generic data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function apiChangeAnsweredStatus(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
{
|
||||
$old = clone QAAnswerMapper::get((int) $request->getData('id'));
|
||||
$new = $this->updateAnsweredStatusFromRequest($request);
|
||||
$this->updateModel($request->header->account, $old, $new, QAAnswerMapper::class, 'answer', $request->getOrigin());
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Answer', 'Answer successfully updated.', $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create category from request.
|
||||
*
|
||||
* @param RequestAbstract $request Request
|
||||
*
|
||||
* @return QAAnswer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function updateAnsweredStatusFromRequest(RequestAbstract $request) : QAAnswer
|
||||
{
|
||||
$answer = QAAnswerMapper::get((int) $request->getData('id'));
|
||||
$answer->isAccepted = $request->getData('accepted', 'bool') ?? false;
|
||||
|
||||
return $answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Api method to create a category
|
||||
*
|
||||
|
|
@ -301,18 +340,9 @@ final class ApiController extends Controller
|
|||
}
|
||||
|
||||
$category = $this->createQACategoryFromRequest($request);
|
||||
$category->setL11n($request->getData('name'), $request->getData('language'));
|
||||
$this->createModel($request->header->account, $category, QACategoryMapper::class, 'category', $request->getOrigin());
|
||||
|
||||
$l11nRequest = new HttpRequest($request->uri);
|
||||
$l11nRequest->setData('category', $category->getId());
|
||||
$l11nRequest->setData('name', $request->getData('name'));
|
||||
$l11nRequest->setData('language', $request->getData('language'));
|
||||
|
||||
$l11nQACategory = $this->createQACategoryL11nFromRequest($l11nRequest);
|
||||
$this->createModel($request->header->account, $l11nQACategory, QACategoryL11nMapper::class, 'tag_l11n', $request->getOrigin());
|
||||
|
||||
$category->setName($l11nQACategory);
|
||||
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Category', 'Category successfully created.', $category);
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +469,7 @@ final class ApiController extends Controller
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function apiChangeQAQuestionVote(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
public function apiChangeQAQuestionVote(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
{
|
||||
if (!empty($val = $this->validateQuestionVote($request))) {
|
||||
$response->set('qa_question_vote', new FormValidation($val));
|
||||
|
|
@ -448,12 +478,13 @@ final class ApiController extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$questionVote = QAQuestionVoteMapper::findVote((int) $reqeust->getData('id'), $request->header->account);
|
||||
$questionVote = QAQuestionVoteMapper::findVote((int) $request->getData('id'), $request->header->account);
|
||||
|
||||
if ($questionVote instanceof NullQAQuestionVote) {
|
||||
if ($questionVote === false || $questionVote instanceof NullQAQuestionVote || $questionVote === null) {
|
||||
$new = new QAQuestionVote();
|
||||
$new->score = (int) $request->getData('type');
|
||||
$new->createdBy = $request->header->account;
|
||||
$new->question = (int) $request->getData('id');
|
||||
$new->createdBy = new NullAccount($request->header->account);
|
||||
|
||||
$this->createModel($request->header->account, $new, QAQuestionVoteMapper::class, 'qa_question_vote', $request->getOrigin());
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Vote', 'Sucessfully voted.', $new);
|
||||
|
|
@ -500,7 +531,7 @@ final class ApiController extends Controller
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function apiChangeQAAnswerVote(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
public function apiChangeQAAnswerVote(RequestAbstract $request, ResponseAbstract $response, $data = null) : void
|
||||
{
|
||||
if (!empty($val = $this->validateAnswerVote($request))) {
|
||||
$response->set('qa_answer_vote', new FormValidation($val));
|
||||
|
|
@ -509,12 +540,13 @@ final class ApiController extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$answerVote = QAAnswerVoteMapper::findVote((int) $reqeust->getData('id'), $request->header->account);
|
||||
$answerVote = QAAnswerVoteMapper::findVote((int) $request->getData('id'), $request->header->account);
|
||||
|
||||
if ($answerVote instanceof NullQAAnswerVote) {
|
||||
if ($answerVote === false || $answerVote instanceof NullQAAnswerVote || $answerVote === null) {
|
||||
$new = new QAAnswerVote();
|
||||
$new->score = (int) $request->getData('type');
|
||||
$new->createdBy = $request->header->account;
|
||||
$new->answer = (int) $request->getData('id');
|
||||
$new->createdBy = new NullAccount($request->header->account);
|
||||
|
||||
$this->createModel($request->header->account, $new, QAAnswerVoteMapper::class, 'qa_answer_vote', $request->getOrigin());
|
||||
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Vote', 'Sucessfully voted.', $new);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QAs\Models;
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
/**
|
||||
* Null model
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\QAs\Models;
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
/**
|
||||
* Null model
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use Modules\Admin\Models\Account;
|
||||
use Modules\Admin\Models\NullAccount;
|
||||
use Modules\Profile\Models\NullProfile;
|
||||
use Modules\Profile\Models\Profile;
|
||||
|
||||
/**
|
||||
* Answer class.
|
||||
|
|
@ -78,10 +78,10 @@ class QAAnswer implements \JsonSerializable
|
|||
/**
|
||||
* Created by.
|
||||
*
|
||||
* @var Account
|
||||
* @var Profile
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public Account $createdBy;
|
||||
public Profile $createdBy;
|
||||
|
||||
/**
|
||||
* Created at.
|
||||
|
|
@ -91,6 +91,14 @@ class QAAnswer implements \JsonSerializable
|
|||
*/
|
||||
public \DateTimeImmutable $createdAt;
|
||||
|
||||
/**
|
||||
* Votes.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private array $votes = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
|
@ -99,7 +107,7 @@ class QAAnswer implements \JsonSerializable
|
|||
public function __construct()
|
||||
{
|
||||
$this->createdAt = new \DateTimeImmutable('now');
|
||||
$this->createdBy = new NullAccount();
|
||||
$this->createdBy = new NullProfile();
|
||||
$this->question = new NullQAQuestion();
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +215,27 @@ class QAAnswer implements \JsonSerializable
|
|||
$this->isAccepted = $accepted;
|
||||
}
|
||||
|
||||
public function getVoteScore() : int
|
||||
{
|
||||
$score = 0;
|
||||
foreach ($this->votes as $vote) {
|
||||
$score += $vote->score;
|
||||
}
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function getAccountVoteScore(int $account) : int
|
||||
{
|
||||
foreach ($this->votes as $vote) {
|
||||
if ($vote->createdBy->getId() === $account) {
|
||||
return $vote->score;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the answer accepted
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
use Modules\Profile\Models\ProfileMapper;
|
||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
|
||||
/**
|
||||
|
|
@ -52,8 +52,9 @@ final class QAAnswerMapper extends DataMapperAbstract
|
|||
*/
|
||||
protected static array $belongsTo = [
|
||||
'createdBy' => [
|
||||
'mapper' => AccountMapper::class,
|
||||
'mapper' => ProfileMapper::class,
|
||||
'external' => 'qa_answer_created_by',
|
||||
'by' => 'account'
|
||||
],
|
||||
'question' => [
|
||||
'mapper' => QAQuestionMapper::class,
|
||||
|
|
@ -61,6 +62,21 @@ final class QAAnswerMapper extends DataMapperAbstract
|
|||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Has many relation.
|
||||
*
|
||||
* @var array<string, array{mapper:string, table:string, self?:?string, external?:?string, column?:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $hasMany = [
|
||||
'votes' => [
|
||||
'mapper' => QAAnswerVoteMapper::class,
|
||||
'table' => 'qa_answer_vote',
|
||||
'self' => 'qa_answer_vote_answer',
|
||||
'external' => null,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class QAAnswerVote
|
|||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $comment = 0;
|
||||
public int $answer = 0;
|
||||
|
||||
/**
|
||||
* Score
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
|||
namespace Modules\QA\Models;
|
||||
|
||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
|
||||
/**
|
||||
* Mapper class.
|
||||
|
|
@ -35,11 +36,24 @@ final class QAAnswerVoteMapper extends DataMapperAbstract
|
|||
protected static array $columns = [
|
||||
'qa_answer_vote_id' => ['name' => 'qa_answer_vote_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'qa_answer_vote_score' => ['name' => 'qa_answer_vote_score', 'type' => 'int', 'internal' => 'score'],
|
||||
'qa_answer_vote_answer' => ['name' => 'qa_answer_vote_comment', 'type' => 'int', 'internal' => 'comment', 'readonly' => true],
|
||||
'qa_answer_vote_answer' => ['name' => 'qa_answer_vote_answer', 'type' => 'int', 'internal' => 'answer', 'readonly' => true],
|
||||
'qa_answer_vote_created_by' => ['name' => 'qa_answer_vote_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||
'qa_answer_vote_created_at' => ['name' => 'qa_answer_vote_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
];
|
||||
|
||||
/**
|
||||
* Belongs to.
|
||||
*
|
||||
* @var array<string, array{mapper:string, external:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $belongsTo = [
|
||||
'createdBy' => [
|
||||
'mapper' => AccountMapper::class,
|
||||
'external' => 'qa_answer_vote_created_by',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
|
|
@ -63,4 +77,16 @@ final class QAAnswerVoteMapper extends DataMapperAbstract
|
|||
* @since 1.0.0
|
||||
*/
|
||||
protected static string $primaryField = 'qa_answer_vote_id';
|
||||
|
||||
public static function findVote(int $question, int $account)
|
||||
{
|
||||
$depth = 3;
|
||||
$query = self::getQuery();
|
||||
$query->where(self::$table . '_' . $depth . '.qa_answer_vote_created_by', '=', $account)
|
||||
->andWhere(self::$table . '_' . $depth . '.qa_answer_vote_answer', '=', $question);
|
||||
|
||||
$results = self::getAllByQuery($query);
|
||||
|
||||
return \reset($results);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class QACategory implements \JsonSerializable
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function getName() : string
|
||||
public function getL11n() : string
|
||||
{
|
||||
return $this->name instanceof QACategoryL11n ? $this->name->getName() : $this->name;
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ class QACategory implements \JsonSerializable
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function setName($name, string $lang = ISO639x1Enum::_EN) : void
|
||||
public function setL11n($name, string $lang = ISO639x1Enum::_EN) : void
|
||||
{
|
||||
if ($name instanceof QACategoryL11n) {
|
||||
$this->name = $name;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Modules\QA\Models;
|
||||
|
||||
use Modules\Admin\Models\NullAccount;
|
||||
use Modules\Profile\Models\NullProfile;
|
||||
use Modules\Tag\Models\Tag;
|
||||
use Modules\Profile\Models\Profile;
|
||||
|
|
@ -117,6 +116,14 @@ class QAQuestion implements \JsonSerializable
|
|||
*/
|
||||
private array $answers = [];
|
||||
|
||||
/**
|
||||
* Votes.
|
||||
*
|
||||
* @var array
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private array $votes = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
|
@ -286,6 +293,32 @@ class QAQuestion implements \JsonSerializable
|
|||
$this->tags = $tags;
|
||||
}
|
||||
|
||||
public function getAnswerCount() : int
|
||||
{
|
||||
return \count($this->answers);
|
||||
}
|
||||
|
||||
public function getVoteScore() : int
|
||||
{
|
||||
$score = 0;
|
||||
foreach ($this->votes as $vote) {
|
||||
$score += $vote->score;
|
||||
}
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
public function getAccountVoteScore(int $account) : int
|
||||
{
|
||||
foreach ($this->votes as $vote) {
|
||||
if ($vote->createdBy->getId() === $account) {
|
||||
return $vote->score;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get answers
|
||||
*
|
||||
|
|
|
|||
|
|
@ -59,6 +59,12 @@ final class QAQuestionMapper extends DataMapperAbstract
|
|||
'self' => 'qa_answer_question',
|
||||
'external' => null,
|
||||
],
|
||||
'votes' => [
|
||||
'mapper' => QAQuestionVoteMapper::class,
|
||||
'table' => 'qa_question_vote',
|
||||
'self' => 'qa_question_vote_question',
|
||||
'external' => null,
|
||||
],
|
||||
'tags' => [
|
||||
'mapper' => TagMapper::class,
|
||||
'table' => 'qa_tag',
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class QAQuestionVote
|
|||
* @var int
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public int $comment = 0;
|
||||
public int $question = 0;
|
||||
|
||||
/**
|
||||
* Score
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ declare(strict_types=1);
|
|||
namespace Modules\QA\Models;
|
||||
|
||||
use phpOMS\DataStorage\Database\DataMapperAbstract;
|
||||
use Modules\Admin\Models\AccountMapper;
|
||||
|
||||
/**
|
||||
* Mapper class.
|
||||
|
|
@ -35,11 +36,24 @@ final class QAQuestionVoteMapper extends DataMapperAbstract
|
|||
protected static array $columns = [
|
||||
'qa_question_vote_id' => ['name' => 'qa_question_vote_id', 'type' => 'int', 'internal' => 'id'],
|
||||
'qa_question_vote_score' => ['name' => 'qa_question_vote_score', 'type' => 'int', 'internal' => 'score'],
|
||||
'qa_question_vote_question' => ['name' => 'qa_question_vote_comment', 'type' => 'int', 'internal' => 'comment', 'readonly' => true],
|
||||
'qa_question_vote_question' => ['name' => 'qa_question_vote_question', 'type' => 'int', 'internal' => 'question', 'readonly' => true],
|
||||
'qa_question_vote_created_by' => ['name' => 'qa_question_vote_created_by', 'type' => 'int', 'internal' => 'createdBy', 'readonly' => true],
|
||||
'qa_question_vote_created_at' => ['name' => 'qa_question_vote_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true],
|
||||
];
|
||||
|
||||
/**
|
||||
* Belongs to.
|
||||
*
|
||||
* @var array<string, array{mapper:string, external:string}>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected static array $belongsTo = [
|
||||
'createdBy' => [
|
||||
'mapper' => AccountMapper::class,
|
||||
'external' => 'qa_question_vote_created_by',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Primary table.
|
||||
*
|
||||
|
|
@ -63,4 +77,16 @@ final class QAQuestionVoteMapper extends DataMapperAbstract
|
|||
* @since 1.0.0
|
||||
*/
|
||||
protected static string $primaryField = 'qa_question_vote_id';
|
||||
|
||||
public static function findVote(int $question, int $account)
|
||||
{
|
||||
$depth = 3;
|
||||
$query = self::getQuery();
|
||||
$query->where(self::$table . '_' . $depth . '.qa_question_vote_created_by', '=', $account)
|
||||
->andWhere(self::$table . '_' . $depth . '.qa_question_vote_question', '=', $question);
|
||||
|
||||
$results = self::getAllByQuery($query);
|
||||
|
||||
return \reset($results);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,27 +12,46 @@
|
|||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
use phpOMS\Uri\UriFactory;
|
||||
use Modules\Media\Models\NullMedia;
|
||||
|
||||
$questions = $this->getData('questions');
|
||||
echo $this->getData('nav')->render(); ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<?php foreach ($questions as $question) : ?>
|
||||
<section class="portlet qa-list">
|
||||
<section class="portlet qa qa-list">
|
||||
<div class="portlet-body">
|
||||
<div class="row middle-xs">
|
||||
<div class="col-xs-1 scores">
|
||||
<span class="score<?= $this->printHtml($question->hasAccepted() ? ' done' : ''); ?>"><?= \count($question->getAnswers()); ?></span>
|
||||
<div class="counter-area">
|
||||
<div class="counter-container">
|
||||
<span class="counter score<?= $this->printHtml($question->hasAccepted() ? ' done' : ' open'); ?>"><?= $question->getAnswerCount(); ?></span>
|
||||
<span class="text">Answers</span>
|
||||
</div>
|
||||
<div class="counter-container">
|
||||
<span class="counter"><?= $question->getVoteScore(); ?></span>
|
||||
<span class="text">Score</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title col-xs-11">
|
||||
<a href="<?= \phpOMS\Uri\UriFactory::build('{/prefix}qa/question?{?}&id=' . $question->getId()); ?>"><?= $this->printHtml($question->name); ?></a>
|
||||
<div class="title">
|
||||
<a href="<?= UriFactory::build('{/prefix}qa/question?{?}&id=' . $question->getId()); ?>"><?= $this->printHtml($question->name); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="portlet-foot">
|
||||
<?php $tags = $question->getTags(); foreach ($tags as $tag) : ?>
|
||||
<span class="tag red"><?= $this->printHtml($tag->getTitle()); ?></span>
|
||||
<?php endforeach; ?>
|
||||
<div class="portlet-foot qa-portlet-foot">
|
||||
<div class="tag-list">
|
||||
<?php $tags = $question->getTags(); foreach ($tags as $tag) : ?>
|
||||
<span class="tag"><?= $tag->icon !== null ? '<i class="' . $this->printHtml($tag->icon ?? '') . '"></i>' : ''; ?><?= $this->printHtml($tag->getL11n()); ?></span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<a class="account-info" href="<?= UriFactory::build('{/prefix}profile/single?{?}&id=' . $question->createdBy->getId()); ?>">
|
||||
<span class="name content"><?= $this->printHtml($question->createdBy->account->name2); ?> <?= $this->printHtml($question->createdBy->account->name1); ?></span>
|
||||
<?php if ($question->createdBy->image !== null && !($question->createdBy->image instanceof NullMedia)) : ?>
|
||||
<img width="40px" alt="<?= $this->getHtml('AccountImage', '0', '0'); ?>" loading="lazy" src="<?= UriFactory::build('{/prefix}' . $question->createdBy->image->getPath()); ?>">
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
|||
|
|
@ -13,37 +13,94 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
use phpOMS\Uri\UriFactory;
|
||||
use Modules\Media\Models\NullMedia;
|
||||
|
||||
/** \Modules\QA\Models\QAQuestion $question */
|
||||
$question = $this->getData('question');
|
||||
$answers = $question->getAnswers();
|
||||
|
||||
/** \Modules\QA\Models\QAAnswer[] $answers */
|
||||
$answers = $question->getAnswers();
|
||||
|
||||
echo $this->getData('nav')->render();
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
<div class="row qa">
|
||||
<div class="col-xs-12">
|
||||
<section class="portlet">
|
||||
<div class="portlet-head"><?= $this->printHtml($question->name); ?></div>
|
||||
<div class="portlet-body">
|
||||
<?= $question->question; ?>
|
||||
<div class="qa-question-view">
|
||||
<div class="score">
|
||||
<div class="counter-area">
|
||||
<div class="counter-container">
|
||||
<i class="fa fa-chevron-up qa-vote<?= $this->printHtml($question->getAccountVoteScore($this->request->header->account) > 0 ? ' voted' : ' open'); ?>"></i>
|
||||
<span class="counter"><?= $question->getVoteScore(); ?></span>
|
||||
<span class="text">Score</span>
|
||||
<i class="fa fa-chevron-down qa-vote<?= $this->printHtml($question->getAccountVoteScore($this->request->header->account) < 0 ? ' voted' : ' open'); ?>"></i>
|
||||
</div>
|
||||
<div class="counter-container">
|
||||
<span class="counter score<?= $this->printHtml($question->hasAccepted() ? ' done' : ' open'); ?>"><?= $question->getAnswerCount(); ?></span>
|
||||
<span class="text">Answers</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inner">
|
||||
<?php if ($question->createdBy->image !== null) : ?>
|
||||
<img alt="<?= $this->getHtml('AccountImage', '0', '0'); ?>" loading="lazy" src="<?= UriFactory::build('{/prefix}' . $question->createdBy->image->getPath()); ?>">
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
<section class="portlet">
|
||||
<div class="portlet-head"><?= $this->printHtml($question->name); ?></div>
|
||||
<div class="portlet-body">
|
||||
<article>
|
||||
<?= $question->question; ?>
|
||||
</article>
|
||||
</div>
|
||||
<div class="portlet-foot qa-portlet-foot">
|
||||
<div class="tag-list">
|
||||
<?php $tags = $question->getTags(); foreach ($tags as $tag) : ?>
|
||||
<span class="tag"><?= $tag->icon !== null ? '<i class="' . $this->printHtml($tag->icon ?? '') . '"></i>' : ''; ?><?= $this->printHtml($tag->getL11n()); ?></span>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<a class="account-info" href="<?= UriFactory::build('{/prefix}profile/single?{?}&id=' . $question->createdBy->getId()); ?>">
|
||||
<span class="name content"><?= $this->printHtml($question->createdBy->account->name2); ?>, <?= $this->printHtml($question->createdBy->account->name1); ?></span>
|
||||
<?php if ($question->createdBy->image !== null && !($question->createdBy->image instanceof NullMedia)) : ?>
|
||||
<img width="40px" alt="<?= $this->getHtml('AccountImage', '0', '0'); ?>" loading="lazy" src="<?= UriFactory::build('{/prefix}' . $question->createdBy->image->getPath()); ?>">
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php foreach ($answers as $answer) : ?>
|
||||
<div class="row">
|
||||
<div class="row qa">
|
||||
<div class="col-xs-12">
|
||||
<section class="portlet">
|
||||
<div class="portlet-body">
|
||||
<?= $answer->answer; ?><?= $this->printHtml($answer->createdAt->format('Y-m-d')); ?><?= $answer->createdBy->getId(); ?><?= $answer->getStatus(); ?><?= $this->printHtml((string) $answer->isAccepted()); ?>
|
||||
<div class="qa-question-view<?= $this->printHtml($answer->isAccepted ? ' accepted' : ''); ?>">
|
||||
<div class="score">
|
||||
<div class="counter-area">
|
||||
<div class="counter-container">
|
||||
<i class="fa fa-chevron-up qa-vote<?= $this->printHtml($answer->getAccountVoteScore($this->request->header->account) > 0 ? ' voted' : ' open'); ?>"></i>
|
||||
<span class="counter"><?= $answer->getVoteScore(); ?></span>
|
||||
<span class="text">Score</span>
|
||||
<i class="fa fa-chevron-down qa-vote<?= $this->printHtml($answer->getAccountVoteScore($this->request->header->account) < 0 ? ' voted' : ' open'); ?>"></i>
|
||||
</div>
|
||||
<div class="counter-container">
|
||||
<i class="fa fa-check qa-accept"></i>
|
||||
<span class="text"><?= $this->printHtml($answer->isAccepted ? 'Accepted' : 'Accept'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="portlet">
|
||||
<div class="portlet-body">
|
||||
<article>
|
||||
<?= $answer->answer; ?>
|
||||
</article>
|
||||
</div>
|
||||
<div class="portlet-foot qa-portlet-foot">
|
||||
<a class="account-info" href="<?= UriFactory::build('{/prefix}profile/single?{?}&id=' . $answer->createdBy->getId()); ?>">
|
||||
<span class="name content"><?= $this->printHtml($answer->createdBy->account->name2); ?> <?= $this->printHtml($answer->createdBy->account->name1); ?></span>
|
||||
<?php if ($answer->createdBy->image !== null && !($answer->createdBy->image instanceof NullMedia)) : ?>
|
||||
<img width="40px" alt="<?= $this->getHtml('AccountImage', '0', '0'); ?>" loading="lazy" src="<?= UriFactory::build('{/prefix}' . $answer->createdBy->image->getPath()); ?>">
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,65 @@
|
|||
.qa-list .score {
|
||||
padding: 10px;
|
||||
margin-right: 10px;
|
||||
border: 1px solid #ccc; }
|
||||
.qa-list .score.closed {
|
||||
background: #f00; }
|
||||
.qa-list .score.open {
|
||||
background: #ff0; }
|
||||
.qa-list .score.done {
|
||||
background: #0f0; }
|
||||
.qa-list .scores {
|
||||
flex-basis: min-content; }
|
||||
.qa-list .title a {
|
||||
font-size: 2rem; }
|
||||
.qa-list .tags {
|
||||
margin-top: 10px; }
|
||||
font-size: 2rem;
|
||||
margin-left: 1rem; }
|
||||
.qa-list .counter-area {
|
||||
flex-direction: row; }
|
||||
.qa-list .counter-container + .counter-container {
|
||||
margin-left: 10px; }
|
||||
|
||||
.qa-question-view {
|
||||
display: flex;
|
||||
flex-direction: row; }
|
||||
.qa-question-view .counter-area {
|
||||
flex-direction: column;
|
||||
margin: 1rem 10px 0 0;
|
||||
min-width: 50px; }
|
||||
.qa-question-view .counter-container + .counter-container {
|
||||
margin-top: 10px; }
|
||||
|
||||
.qa .qa-accept {
|
||||
font-size: 2rem;
|
||||
color: #ccc;
|
||||
cursor: pointer; }
|
||||
.qa .accepted .qa-accept {
|
||||
color: #81e27d; }
|
||||
.qa .accepted .portlet {
|
||||
border-top: 3px solid #81e27d; }
|
||||
.qa .qa-vote {
|
||||
font-size: 2rem;
|
||||
color: #ccc;
|
||||
cursor: pointer; }
|
||||
.qa .qa-vote.voted {
|
||||
color: #81e27d; }
|
||||
.qa .counter-area {
|
||||
display: flex; }
|
||||
.qa .counter-area .counter-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center; }
|
||||
.qa .counter-area .counter {
|
||||
width: 2.3rem;
|
||||
height: 2.8rem;
|
||||
border: 1px solid #ccc;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff; }
|
||||
.qa .counter-area .text {
|
||||
font-size: .8rem; }
|
||||
.qa .score.closed {
|
||||
background: #f00; }
|
||||
.qa .score.open {
|
||||
background: #f8ffa8; }
|
||||
.qa .score.done {
|
||||
background: #81e27d; }
|
||||
.qa .qa-portlet-foot {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: top; }
|
||||
.qa .qa-portlet-foot .account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto; }
|
||||
.qa .qa-portlet-foot .account-info .name {
|
||||
margin-right: 10px; }
|
||||
|
|
|
|||
|
|
@ -1,33 +1,114 @@
|
|||
.qa-list {
|
||||
.title {
|
||||
a {
|
||||
font-size: 2rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.counter-area {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.counter-container+.counter-container {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.qa-question-view {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.counter-area {
|
||||
flex-direction: column;
|
||||
margin: 1rem 10px 0 0;
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
.counter-container+.counter-container {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.qa {
|
||||
.qa-accept {
|
||||
font-size: 2rem;
|
||||
color: #ccc;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.accepted {
|
||||
.qa-accept {
|
||||
color: #81e27d;
|
||||
}
|
||||
|
||||
.portlet {
|
||||
border-top: 3px solid #81e27d;
|
||||
}
|
||||
}
|
||||
|
||||
.qa-vote {
|
||||
font-size: 2rem;
|
||||
color: #ccc;
|
||||
cursor: pointer;
|
||||
|
||||
&.voted {
|
||||
color: #81e27d;
|
||||
}
|
||||
}
|
||||
|
||||
.counter-area {
|
||||
display: flex;
|
||||
|
||||
.counter-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.counter {
|
||||
width: 2.3rem;
|
||||
height: 2.8rem;
|
||||
border: 1px solid #ccc;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: .8rem;
|
||||
}
|
||||
}
|
||||
|
||||
.score {
|
||||
&.closed {
|
||||
background: #f00;
|
||||
}
|
||||
|
||||
&.open {
|
||||
background: #ff0;
|
||||
background: #f8ffa8;
|
||||
}
|
||||
|
||||
&.done {
|
||||
background: #0f0;
|
||||
}
|
||||
|
||||
padding: 10px;
|
||||
margin-right: 10px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.scores {
|
||||
flex-basis: min-content;
|
||||
}
|
||||
|
||||
.title {
|
||||
a {
|
||||
font-size: 2rem;
|
||||
background: #81e27d;
|
||||
}
|
||||
}
|
||||
|
||||
.tags {
|
||||
margin-top: 10px;
|
||||
.qa-portlet-foot {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: top;
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
|
||||
.name {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user