Add category order (#2592)

* Add category order

Each category has a new 'priority' attribute. It is used to sort categories in
views. Categories with the same priority are sorted alphabetically. Categories
with no priority are displayed after those with one.

For example, if we have the following categories:
- A (priority: 2)
- B (no priority)
- C (priority: 1)
- D (priority: 2)
- E (no priority)
- F (priority: 1)

They will be displayed in the following order:
- C
- F
- A
- D
- B
- E

See #190

* Shorten help text

It took too much room and will not be so necessary once we have drag &
drop
This commit is contained in:
Alexis Degrugillier
2019-10-26 13:16:15 +02:00
committed by Alexandre Alapetite
parent 3c49986ec8
commit f6e10579f2
21 changed files with 71 additions and 5 deletions

View File

@@ -173,7 +173,7 @@ class FreshRSS_index_Controller extends Minz_ActionController {
private function updateContext() {
if (empty(FreshRSS_Context::$categories)) {
$catDAO = FreshRSS_Factory::createCategoryDao();
FreshRSS_Context::$categories = $catDAO->listCategories();
FreshRSS_Context::$categories = $catDAO->listSortedCategories();
}
// Update number of read / unread variables.

View File

@@ -19,7 +19,7 @@ class FreshRSS_subscription_Controller extends Minz_ActionController {
$catDAO->checkDefault();
$feedDAO->updateTTL();
$this->view->categories = $catDAO->listCategories(false);
$this->view->categories = $catDAO->listSortedCategories(false);
$this->view->default_category = $catDAO->getDefault();
}
@@ -216,6 +216,9 @@ class FreshRSS_subscription_Controller extends Minz_ActionController {
]);
}
$position = Minz_Request::param('position');
$category->_attributes('position', '' === $position ? null : (int) $position);
$values = [
'name' => Minz_Request::param('name', ''),
'attributes' => $category->attributes(),

View File

@@ -98,14 +98,14 @@ class FreshRSS_Category extends Minz_Model {
}
public function _attributes($key, $value) {
if ($key == '') {
if ('' == $key) {
if (is_string($value)) {
$value = json_decode($value, true);
}
if (is_array($value)) {
$this->attributes = $value;
}
} elseif ($value === null) {
} elseif (null === $value) {
unset($this->attributes[$key]);
} else {
$this->attributes[$key] = $value;

View File

@@ -201,6 +201,29 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable
}
}
public function listSortedCategories($prePopulateFeeds = true, $details = false) {
$categories = $this->listCategories($prePopulateFeeds, $details);
if (!is_array($categories)) {
return $categories;
}
usort($categories, function ($a, $b) {
$aPosition = $a->attributes('position');
$bPosition = $b->attributes('position');
if ($aPosition === $bPosition) {
return ($a->name() < $b->name()) ? -1 : 1;
} elseif (null === $aPosition) {
return 1;
} elseif (null === $bPosition) {
return -1;
}
return ($aPosition < $bPosition) ? -1 : 1;
});
return $categories;
}
public function listCategories($prePopulateFeeds = true, $details = false) {
if ($prePopulateFeeds) {
$sql = 'SELECT c.id AS c_id, c.name AS c_name, c.attributes AS c_attributes, '
@@ -343,6 +366,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable
$feedDao->daoToFeed($feedsDao, $previousLine['c_id'])
);
$cat->_id($previousLine['c_id']);
$cat->_attributes('', $previousLine['c_attributes']);
$list[$previousLine['c_id']] = $cat;
$feedsDao = array(); //Prepare for next category
@@ -359,6 +383,7 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo implements FreshRSS_Searchable
$feedDao->daoToFeed($feedsDao, $previousLine['c_id'])
);
$cat->_id($previousLine['c_id']);
$cat->_attributes('', $previousLine['c_attributes']);
$list[$previousLine['c_id']] = $cat;
}

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Vyprázdit kategorii',
'information' => 'Informace',
'new' => 'Nová kategorie',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Název',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Leere Kategorie',
'information' => 'Information',
'new' => 'Neue Kategorie',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Titel',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Empty category',
'information' => 'Information',
'new' => 'New category',
'position' => 'Display position',
'position_help' => 'To control category sort order',
'title' => 'Title',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Vaciar categoría',
'information' => 'Información',
'new' => 'Nueva categoría',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Título',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Catégorie vide',
'information' => 'Informations',
'new' => 'Nouvelle catégorie',
'position' => 'Position daffichage',
'position_help' => 'Pour contrôler lordre de tri des catégories',
'title' => 'Titre',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Empty category', //TODO - Translation
'information' => 'מידע',
'new' => 'קטגוריה חדשה',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'כותרת',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Categoria vuota',
'information' => 'Informazioni',
'new' => 'Nuova categoria',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Titolo',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => '빈 카테고리',
'information' => '정보',
'new' => '새 카테고리',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => '제목',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Lege categorie',
'information' => 'Informatie',
'new' => 'Nieuwe categorie',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Titel',
),
'feed' => array(

View File

@@ -16,6 +16,8 @@ return array(
'empty' => 'Categoria voida',
'information' => 'Informacions',
'new' => 'Nòva categoria',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Títol',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Categoria vazia',
'information' => 'Informações',
'new' => 'Nova categoria',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Título',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Empty category', //TODO - Translation
'information' => 'Information', //TODO - Translation
'new' => 'New category', //TODO - Translation
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Title', //TODO - Translation
),
'feed' => array(

View File

@@ -16,6 +16,8 @@ return array(
'empty' => 'Prázdna kategória',
'information' => 'Informácia',
'new' => 'Nová kategória',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Názov',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => 'Boş kategori',
'information' => 'Bilgi',
'new' => 'Yeni kategori',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => 'Başlık',
),
'feed' => array(

View File

@@ -17,6 +17,8 @@ return array(
'empty' => '空分类',
'information' => '信息',
'new' => '新分类',
'position' => 'Display position', //TODO - Translation
'position_help' => 'To control category sort order', //TODO - Translation
'title' => '标题',
),
'feed' => array(

View File

@@ -63,11 +63,12 @@
<?php
foreach ($this->categories as $cat) {
$feeds = $cat->feeds();
$position = $cat->attributes('position');
if (!empty($feeds)) {
$c_active = FreshRSS_Context::isCurrentGet('c_' . $cat->id());
$c_show = $c_active || FreshRSS_Context::$user_conf->display_categories;
?>
<li class="tree-folder category<?= $c_active ? ' active' : '' ?>" data-unread="<?= $cat->nbNotRead() ?>">
<li class="tree-folder category<?= $c_active ? ' active' : '' ?>"<?= null === $position ? '' : "data-position='$position'" ?> data-unread="<?= $cat->nbNotRead() ?>">
<div class="tree-folder-title">
<a class="dropdown-toggle" href="#"><?= _i($c_show ? 'up' : 'down') ?></a>
<a class="title<?= $cat->hasFeedsWithError() ? ' error' : '' ?>" data-unread="<?= format_number($cat->nbNotRead()) ?>" href="<?= _url('index', $actual_view, 'get', 'c_' . $cat->id()) ?>"><?= $cat->name() ?></a>

View File

@@ -17,6 +17,13 @@
?> />
</div>
</div>
<div class="form-group">
<label class="group-name" for="position"><?= _t('sub.category.position') ?></label>
<div class="group-controls">
<input type="number" name="position" id="position" min="1" value="<?= $this->category->attributes('position') ?>" />
<?= _i('help') ?> <?= _t('sub.category.position_help') ?>
</div>
</div>
<div class="form-group form-actions">
<div class="group-controls">