create draft

This commit is contained in:
Dennis Eichhorn 2021-06-24 00:08:15 +02:00
parent 24d2494c6e
commit 356237d0f8
16 changed files with 470 additions and 96 deletions

View File

@ -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);

View File

@ -12,7 +12,7 @@
*/
declare(strict_types=1);
namespace Modules\QAs\Models;
namespace Modules\QA\Models;
/**
* Null model

View File

@ -12,7 +12,7 @@
*/
declare(strict_types=1);
namespace Modules\QAs\Models;
namespace Modules\QA\Models;
/**
* Null model

View File

@ -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
*

View File

@ -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.
*

View File

@ -57,7 +57,7 @@ class QAAnswerVote
* @var int
* @since 1.0.0
*/
public int $comment = 0;
public int $answer = 0;
/**
* Score

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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
*

View File

@ -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',

View File

@ -57,7 +57,7 @@ class QAQuestionVote
* @var int
* @since 1.0.0
*/
public int $comment = 0;
public int $question = 0;
/**
* Score

View File

@ -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);
}
}

View File

@ -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; ?>

View File

@ -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; ?>

View File

@ -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; }

View File

@ -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;
}
}
}
}
}