Browse Source

Search and listing design tweaks

Jordi Boggiano 9 years ago
parent
commit
ae29574174

+ 3 - 3
app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig

@@ -25,8 +25,8 @@
         </div>
     </div>
 
-    <div class="notifications">
-        <label class="checkbox" for="failureNotifications">
+    <div class="notifications form-group">
+        <label>
             {{ form_widget(form.failureNotifications) }}
             Notify me of package update failures
         </label>
@@ -47,4 +47,4 @@
 </form>
 
 <div class="col-md-2">
-</div>
+</div>

+ 2 - 2
app/Resources/FOSUserBundle/views/Profile/show.html.twig

@@ -5,7 +5,7 @@
 {% block fos_user_content %}
 <section class="col-md-9">
     {%- if app.user.apiToken %}
-        <h3 class="font-normal">Your API Token</h3>
+        <h3 class="font-normal profile-title">Your API Token</h3>
 
         <div class="input-group clearfix">
             <input id="api-token" type="text" class="form-control" value="" data-api-token="{{ app.user.apiToken }}" readonly="readonly">
@@ -29,7 +29,7 @@
         <hr>
     {%- endif %}
 
-    {% embed "PackagistWebBundle:Web:list.html.twig" with {'noLayout': 'true'} %}
+    {% embed "PackagistWebBundle:Web:list.html.twig" with {noLayout: 'true', showAutoUpdateWarning: true} %}
         {% block content_title %}
             <h3 class="font-normal">Your packages</h3>
         {% endblock %}

+ 1 - 1
src/Packagist/WebBundle/Controller/WebController.php

@@ -1329,7 +1329,7 @@ class WebController extends Controller
         return array(
             'downloads' => array(
                 'title' => 'Sort by downloads',
-                'class' => 'glyphicon-download',
+                'class' => 'glyphicon-arrow-down',
                 'arrowClass' => $makeDefaultArrow('downloads'),
                 'href' => $makeDefaultHref('downloads')
             ),

+ 11 - 10
src/Packagist/WebBundle/Menu/MenuBuilder.php

@@ -28,11 +28,7 @@ class MenuBuilder
         $menu = $this->factory->createItem('root');
         $menu->setChildrenAttribute('class', 'list-unstyled');
 
-        $menu->addChild('Profile', array('label' => '<span class="icon-vcard"></span>Profile', 'route' => 'fos_user_profile_show', 'extras' => array('safe_label' => true)));
-        $menu->addChild('Settings', array('label' => '<span class="icon-tools"></span>Settings', 'route' => 'fos_user_profile_edit', 'extras' => array('safe_label' => true)));
-        $menu->addChild('Change password', array('label' => '<span class="icon-key"></span>Change password', 'route' => 'fos_user_change_password', 'extras' => array('safe_label' => true)));
-        $menu->addChild('My packages', array('label' => '<span class="icon-box"></span>My packages', 'route' => 'user_packages', 'routeParameters' => array('name' => $this->username), 'extras' => array('safe_label' => true)));
-        $menu->addChild('My favorites', array('label' => '<span class="icon-leaf"></span>My favorites', 'route' => 'user_favorites', 'routeParameters' => array('name' => $this->username), 'extras' => array('safe_label' => true)));
+        $this->addProfileMenu($menu);
         $menu->addChild('hr', array('label' => '<hr>', 'labelAttributes' => array('class' => 'normal'), 'extras' => array('safe_label' => true)));
         $menu->addChild('Logout', array('label' => '<span class="icon-off"></span>Logout', 'route' => 'logout', 'extras' => array('safe_label' => true)));
 
@@ -44,12 +40,17 @@ class MenuBuilder
         $menu = $this->factory->createItem('root');
         $menu->setChildrenAttribute('class', 'nav nav-tabs nav-stacked');
 
-        $menu->addChild('Profile', array('label' => '<span class="icon-vcard"></span>Profile', 'route' => 'fos_user_profile_show', 'extras' => array('safe_label' => true)));
-        $menu->addChild('Edit your information', array('label' => '<span class="icon-tools"></span>Edit your information', 'route' => 'fos_user_profile_edit', 'extras' => array('safe_label' => true)));
-        $menu->addChild('Change password', array('label' => '<span class="icon-key"></span>Change password', 'route' => 'fos_user_change_password', 'extras' => array('safe_label' => true)));
-        $menu->addChild('View your packages', array('label' => '<span class="icon-box"></span>View your packages', 'route' => 'user_packages', 'routeParameters' => array('name' => $this->username), 'extras' => array('safe_label' => true)));
-        $menu->addChild('View your favorites', array('label' => '<span class="icon-leaf"></span>View your favorites', 'route' => 'user_favorites', 'routeParameters' => array('name' => $this->username), 'extras' => array('safe_label' => true)));
+        $this->addProfileMenu($menu);
 
         return $menu;
     }
+
+    private function addProfileMenu($menu)
+    {
+        $menu->addChild('Profile', array('label' => '<span class="icon-vcard"></span>Profile', 'route' => 'fos_user_profile_show', 'extras' => array('safe_label' => true)));
+        $menu->addChild('Settings', array('label' => '<span class="icon-tools"></span>Settings', 'route' => 'fos_user_profile_edit', 'extras' => array('safe_label' => true)));
+        $menu->addChild('Change password', array('label' => '<span class="icon-key"></span>Change password', 'route' => 'fos_user_change_password', 'extras' => array('safe_label' => true)));
+        $menu->addChild('My packages', array('label' => '<span class="icon-box"></span>My packages', 'route' => 'user_packages', 'routeParameters' => array('name' => $this->username), 'extras' => array('safe_label' => true)));
+        $menu->addChild('My favorites', array('label' => '<span class="icon-leaf"></span>My favorites', 'route' => 'user_favorites', 'routeParameters' => array('name' => $this->username), 'extras' => array('safe_label' => true)));
+    }
 }

+ 38 - 64
src/Packagist/WebBundle/Resources/public/css/main.css

@@ -493,19 +493,25 @@ ul.packages h1 {
 }
 
 ul.packages .metadata {
-  float: right;
   color: #555;
+  font-size: 15px;
+}
+ul.packages .metadata .glyphicon {
+  top: 3px;
+  margin: 0 1px;
   font-size: 18px;
-  margin-right: 10px;
-  padding-top: 8px;
+}
+ul.packages .metadata-block {
+  display: block;
+  margin-bottom: 10px;
+}
+ul.packages .metadata-block:last-child {
+  margin-bottom: 0;
 }
 
 ul.packages .abandoned {
-  float: right;
-  color: #800;
-  font-size: 12px;
-  margin-right: 10px;
-  margin-top: 5px;
+  color: #ff4533;
+  font-size: 18px;
 }
 
 .input-group input:focus:invalid:focus {
@@ -675,37 +681,26 @@ ul.packages .abandoned {
 
 /* Search */
 #search_query_query {
-  width: 890px;
-}
-.no-js #search_query_query {
-  width: 780px;
+  display: inline;
 }
 
 .wrapper-blue .sortable a {
   border: 0;
 }
-.sortable #search_query_query {
-  width: 777px;
-  display: inline;
-}
-.sortable .no-js #search_query_query {
-  width: 600px;
-}
 
 #search_query_orderBys {
   display: none;
 }
 
 .sortable .glyphicon.active {
-  color: #0013ff;
+  color: #00335D;
 }
 
 .sortable #order-bys-wrapper {
-  margin-left: 0.7em;
-  display: inline;
   font-size: 24px;
   position: relative;
-  top: 6px;
+  top: 15px;
+  margin-left: -12px;
 }
 
 .sortable .order-by-group .icon:first-child {
@@ -720,6 +715,7 @@ ul.packages .abandoned {
 .sortable #order-bys-wrapper a.clear {
   width: auto;
   margin-right: 0px;
+  margin-left: 5px;
 }
 
 #search-form .submit-wrapper {
@@ -743,14 +739,6 @@ ul.packages .abandoned {
 }
 
 
-.package .action.abandon input, .package .action.un-abandon input {
-  background: #ec400b;
-  background: -moz-linear-gradient(top, #ec400b 0%, #f5813f 100%);
-  background: -webkit-linear-gradient(top, #ec400b 0%, #f5813f 100%);
-  background: -o-linear-gradient(top, #ec400b 0%, #f5813f 100%);
-  background: -ms-linear-gradient(top, #ec400b 0%, #f5813f 100%);
-  background: linear-gradient(top, #ec400b 0%, #f5813f 100%);
-}
 .package .action.delete-version {
   float: none;
   display: inline-block;
@@ -763,7 +751,12 @@ ul.packages .abandoned {
 .package .action input.loading {
   background-position: 10px center;
   background-image: url("../img/loader.gif");
-  padding-left: 30px;
+  background-repeat: no-repeat;
+  padding-left: 35px;
+}
+.package .action {
+  margin-left: 5px;
+  margin-bottom: 5px;
 }
 
 .btn-github.disabled {
@@ -792,28 +785,12 @@ ul.packages .abandoned {
 }
 
 .pagination ul > li > a, .pagination ul > li > span {
-    background-color: #E8E2D8;
-    border-radius: 40px 40px 40px 40px;
-    color: #55606E;
-    float: left;
     font-size: 12px;
     font-weight: bold;
     height: 40px;
     text-align: center;
     text-decoration: none;
-    width: 40px;
-}
-
-.pagination ul > li:first-child > a, .pagination ul > li:first-child > span {
-    border-bottom-left-radius: 40px;
-    border-left-width: inherit;
-    border-top-left-radius: 40px;
-}
-
-.pagination ul > li:last-child > a, .pagination ul > li:last-child > span {
-    border-bottom-left-radius: 40px;
-    border-left-width: inherit;
-    border-top-left-radius: 40px;
+    min-width: 20px;
 }
 
 .legend {
@@ -843,13 +820,10 @@ pre {
 
 
 .wrapper .content h2.title, .wrapper .content h3.title {
-    margin: -15px 0 15px;
+    margin: -5px 0 15px;
     padding: 0 0 15px;
     border-bottom: 1px solid #DDDFE1;
     color: #2c3e50;
-    font-size: 55px;
-    font-weight: 600;
-    line-height: 60px;
 }
 
 .wrapper .content h3.title {
@@ -857,6 +831,10 @@ pre {
     font-size: 40px;
     line-height: 45px;
 }
+.content h3.profile-title {
+    margin-top: 0;
+    margin-bottom: 20px;
+}
 
 .wrapper .content h2 {
     font-size: 36px;
@@ -877,7 +855,7 @@ pre {
 }
 
 .wrapper .content p {
-    line-height: 20px;
+    line-height: 150%;
     margin: 0;
     padding: 10px 0;
     vertical-align: baseline;
@@ -920,10 +898,9 @@ pre {
 }
 
 
-.notifications {
+.fos_user_profile_edit .notifications {
+    margin: 10px 0;
     float: left;
-    width: 99%;
-    margin-bottom: 10px;
 }
 
 
@@ -946,10 +923,10 @@ pre {
     font-size: 14px;
 }
 
-.packages li {
+.packages > li {
     padding: 5px 15px;
     margin-bottom: 10px;
-    background: #f0f5f3;
+    background: #F3F4F5;
     border-radius: 4px;
 }
 
@@ -959,17 +936,14 @@ pre {
 }
 
 .packages li h4 {
-    color: #2c3e50;
     font-size: 20px;
     margin-bottom: 0;
 }
 
 .packages li h4 small {
     margin-left: 5px;
-}
-
-.packages li .metadata span {
-    margin-left: 8px;
+    color: #83C129;
+    font-size: 16px;
 }
 
 [class^="icon-"]:before,

+ 7 - 33
src/Packagist/WebBundle/Resources/public/js/search.js

@@ -33,10 +33,6 @@
 
     doSearch = function () {
         var currentQuery,
-            orderBys,
-            orderBysStrParts,
-            joinedOrderBys,
-            joinedOrderBysQryStrPart,
             q,
             pathname,
             urlPrefix,
@@ -62,29 +58,9 @@
             return;
         }
 
-        if (window.history.pushState) {
-            orderBys = [];
-
-            $('#search_query_orderBys > div').each(function (i, e) {
-                var sort,
-                    order;
-                sort = $(e).find('input').val();
-                order = $(e).find('select').val();
-
-                orderBys.push({
-                    sort: sort,
-                    order: order
-                });
-            });
-
-            orderBysStrParts = [];
-
-            orderBys.forEach(function (e, i) {
-                orderBysStrParts.push('orderBys[' + i + '][sort]=' + e.sort + '&orderBys[' + i + '][order]=' + e.order);
-            });
-
-            joinedOrderBys = orderBysStrParts.join('&');
+        $('.order-by-group .active').removeClass('active');
 
+        if (window.history.pushState) {
             q = encodeURIComponent($('input[type="search"]', form).val());
 
             pathname = window.location.pathname;
@@ -97,13 +73,7 @@
                 urlPrefix = '';
             }
 
-            if (joinedOrderBys === '') {
-                joinedOrderBysQryStrPart = '';
-            } else {
-                joinedOrderBysQryStrPart = '&' + joinedOrderBys;
-            }
-
-            url = urlPrefix + '/search/?q=' + q + joinedOrderBysQryStrPart;
+            url = urlPrefix + '/search/?q=' + q;
             title = 'Search';
 
             if (firstQuery) {
@@ -153,6 +123,10 @@
         currentSelected = list.find('ul.packages li.selected');
         nextSelected = (keymap.down === event.which) ? currentSelected.next('li') : currentSelected.prev('li');
 
+        if (currentSelected.length === 0 && keymap.down === event.which) {
+            currentSelected = list.find('ul.packages li:first').addClass('selected');
+        }
+
         if (keymap.enter === event.which && currentSelected.data('url')) {
             window.location = currentSelected.data('url');
             return;

+ 14 - 10
src/Packagist/WebBundle/Resources/views/Package/abandon.html.twig

@@ -3,20 +3,24 @@
 {% block title %}{{ package.name }} - {{ parent() }}{% endblock %}
 
 {% block content %}
-    <div class="box">
-        <h1>
-            <a href="{{ path("view_vendor", {vendor: package.vendor}) }}">{{ package.vendor }}/</a><a href="{{ path("view_package", {name: package.name}) }}">{{ package.packageName }}</a>
-        </h1>
+<h2 class="title">
+    <a href="{{ path("view_vendor", {vendor: package.vendor}) }}">{{ package.vendor }}/</a><a href="{{ path("view_package", {name: package.name}) }}">{{ package.packageName }}</a>
+</h2 class="title">
 
+<section class="row">
+    <form method="post" {{ form_enctype(form) }} class="col-sm-6">
+        {{ form_widget(form) }}
+
+        <hr>
+
+        <input class="btn btn-block btn-default btn-lg" type="submit" value="Abandon Package" />
+    </form>
+
+    <div class="col-sm-6">
         <p>You are about to mark this package as abandoned. This will alert users that this package will no longer be maintained.</p>
         <p>If you are handing this project over to a new maintainer or know of a package that replaces it, please use
             the field below to point users to the new package. In case you cannot point them to a new package, this one
             will be tagged as abandoned and a replacement can be added later.</p>
-
-        <form method="post" {{ form_enctype(form) }}>
-            {{ form_widget(form) }}
-
-            <input type="submit" value="Abandon Package" />
-        </form>
     </div>
+</section>
 {% endblock %}

+ 4 - 4
src/Packagist/WebBundle/Resources/views/User/favorites.html.twig

@@ -22,16 +22,16 @@
 <section class="row">
     {% if isActualUser %}
         <section class="col-md-3">
-            {{ knp_menu_render('profile_menu', {'currentClass': 'active', 'allow_safe_labels': true}) }}
+            {{ knp_menu_render('profile_menu', {currentClass: 'active', allow_safe_labels: true}) }}
         </section>
     {% endif %}
 
     <section class="{{ isActualUser ? 'col-md-9' : 'col-md-12' }}">
-        {% embed "PackagistWebBundle:Web:list.html.twig" with {'noLayout': 'true'} %}
+        {% embed "PackagistWebBundle:Web:list.html.twig" with {noLayout: 'true', showAutoUpdateWarning: isActualUser} %}
             {% block content_title %}
-                <h3 class="font-normal">{{ isActualUser ? 'Your' : user.username~'\'s' }} favorite packages</h3>
+                <h3 class="font-normal profile-title">{{ isActualUser ? 'Your' : user.username~'\'s' }} favorite packages</h3>
             {% endblock %}
         {% endembed %}
     </section>
 </section>
-{% endblock %}
+{% endblock %}

+ 3 - 3
src/Packagist/WebBundle/Resources/views/User/packages.html.twig

@@ -27,11 +27,11 @@
     {% endif %}
 
     <section class="{{ isActualUser ? 'col-md-9' : 'col-md-12' }}">
-        {% embed "PackagistWebBundle:Web:list.html.twig" with {'noLayout': 'true'} %}
+        {% embed "PackagistWebBundle:Web:list.html.twig" with {noLayout: 'true', showAutoUpdateWarning: isActualUser} %}
             {% block content_title %}
-                <h3 class="font-normal">Packages maintained by {{ isActualUser ? 'you' : user.username }}</h3>
+                <h3 class="font-normal profile-title">Packages maintained by {{ isActualUser ? 'you' : user.username }}</h3>
             {% endblock %}
         {% endembed %}
     </section>
 </section>
-{% endblock %}
+{% endblock %}

+ 5 - 3
src/Packagist/WebBundle/Resources/views/User/profile.html.twig

@@ -2,6 +2,8 @@
 
 {% import "PackagistWebBundle::macros.html.twig" as macros %}
 
+{% set isActualUser = app.user and app.user.username is sameas(user.username) %}
+
 {% block content %}
 <h2 class="title">
     {{ user.username }}
@@ -15,11 +17,11 @@
 
 <section class="row">
     <section class="col-md-12">
-        {% embed "PackagistWebBundle:Web:list.html.twig" with {'noLayout': 'true'} %}
+        {% embed "PackagistWebBundle:Web:list.html.twig" with {noLayout: 'true', showAutoUpdateWarning: isActualUser} %}
             {% block content_title %}
-                <h3 class="font-normal">{{ user.username }}'s packages</h3>
+                <h3 class="font-normal profile-title">{{ user.username }}'s packages</h3>
             {% endblock %}
         {% endembed %}
     </section>
 </section>
-{% endblock %}
+{% endblock %}

+ 1 - 1
src/Packagist/WebBundle/Resources/views/Web/list.html.twig

@@ -7,7 +7,7 @@
 
     {% block list %}
         {% if packages|length %}
-            {{ macros.listPackages(packages, paginate is not defined or paginate, false, meta|default(null)) }}
+            {{ macros.listPackages(packages, paginate is not defined or paginate, showAutoUpdateWarning|default(false), meta|default(null)) }}
         {% else %}
             <p>No packages found.</p>
         {% endif %}

+ 1 - 1
src/Packagist/WebBundle/Resources/views/Web/search.html.twig

@@ -5,7 +5,7 @@
     {% endblock %}
 
     {% block content %}
-        <div class="search-results">
+        <div class="search-list">
             {{ block('list') }}
         </div>
     {% endblock %}

+ 7 - 6
src/Packagist/WebBundle/Resources/views/Web/searchForm.html.twig

@@ -1,22 +1,23 @@
 <form id="search-form" action="{{ path('search.ajax') }}" method="GET" {{ form_enctype(searchForm) }} autocomplete="off">
-    <div class="{% if orderBys is defined %}sortable{% endif %}">
-        {{ form_errors(searchForm.query) }}
-        {{ form_widget(searchForm.query, {'attr': {'autocomplete': 'off', 'autofocus': 'autofocus', 'placeholder': 'Search packages...', 'tabindex': 1}}) }}
+    <div class="{% if orderBys is defined %}sortable{% endif %} row">
+        <div class="hidden">{{ form_errors(searchForm.query) }}</div>
+        <div class="col-xs-8 col-lg-10">
+            {{ form_widget(searchForm.query, {'attr': {'autocomplete': 'off', 'autofocus': 'autofocus', 'placeholder': 'Search packages...', 'tabindex': 1}}) }}
+        </div>
 
         {% set hasActiveOrderBy = false %}
         {% spaceless %}
-        <div id="order-bys-wrapper"{% if searchForm.vars.value.query is empty %} class="hidden"{% endif %}>
+        <div id="order-bys-wrapper" class="col-xs-4 col-lg-2{% if searchForm.vars.value.query is empty %} hidden{% endif %}">
             {% for sort, param in orderBys %}
                 <a title="{{ param.title }}" href="{{ param.href }}" class="order-by-group">
                     <i class="glyphicon {{ param.class }}{% if param.arrowClass is not empty %} active{% endif %}"></i>
                     {% if param.arrowClass is not empty %}
-                        <i class="glyphicon {{ param.arrowClass }} active"></i>
                         {% set hasActiveOrderBy = true %}
                     {% endif %}
                 </a>
             {% endfor %}
             {% if hasActiveOrderBy %}
-                <a title="Clear order bys" href="?q={{ searchForm.vars.value.query }} active" class="clear">
+                <a title="Clear order bys" href="?q={{ searchForm.vars.value.query }}" class="clear active">
                     <i class="glyphicon glyphicon-remove-circle"></i>
                 </a>
             {% endif %}

+ 50 - 41
src/Packagist/WebBundle/Resources/views/Web/viewPackage.html.twig

@@ -1,5 +1,7 @@
 {% extends "PackagistWebBundle::layout.html.twig" %}
 
+{% set showSearchDesc = 'hide' %}
+
 {% block title %}{{ package.name }} - {{ parent() }}{% endblock %}
 
 {% block head_feeds %}
@@ -15,43 +17,50 @@
 {% block content %}
     <div class="box">
         <div class="package"{% if app.user and package.crawledAt is null and (is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user)) %} data-force-crawl="true"{% endif %}>
+            <section class="row">
+                <div class="col-sm-6 col-md-8">
+                    <h2 class="title">
+                        {% if is_favorite is defined %}
+                            <i class="mark-favorite icon-star{% if not is_favorite %}-empty{% endif %}" data-remove-url="{{ path('user_remove_fav', {name: app.user.username, package: package.name}) }}" data-add-url="{{ path('user_add_fav', {name: app.user.username}) }}" data-package="{{ package.name }}"></i>
+                        {% endif %}
+                        <a href="{{ path("view_vendor", {"vendor": package.vendor}) }}">{{ package.vendor }}/</a>{{ package.packageName }}
+                        <a id="copy" data-clipboard-text="{{ package.name }}" title="Copy to clipboard"><i class="icon-copy"></i></a>
+                    </h2>
+                </div>
+
+                <div class="col-sm-6 col-md-4">
+                    {% if is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user) %}
+                        <form class="pull-right action" action="{{ path("edit_package", {name: package.name}) }}">
+                            <input class="btn btn-default" type="submit" value="Edit" />
+                        </form>
+                    {% endif %}
+                    {% if is_granted('ROLE_UPDATE_PACKAGES') or package.maintainers.contains(app.user) %}
+                        <form class="force-update pull-right action" action="{{ path('update_package', {name: package.name}) }}" method="POST">
+                            <input type="hidden" name="_method" value="PUT" />
+                            <input type="hidden" name="update" value="1" />
+                            <input class="btn btn-success" type="submit" value="Update" />
+                        </form>
+                    {% endif %}
+                    {% if deleteForm is defined %}
+                        <form class="delete pull-right action" action="{{ path('delete_package', {name: package.name}) }}" method="POST">
+                            <input type="hidden" name="_method" value="DELETE" />
+                            {{ form_widget(deleteForm._token) }}
+                            <input class="btn btn-danger" type="submit" value="Delete" />
+                        </form>
+                    {% endif %}
+                    {% if (is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user)) and not package.abandoned %}
+                        <form class="pull-right action abandon" action="{{ path('abandon_package', {name: package.name}) }}">
+                            <input class="btn btn-warning" type="submit" value="Abandon" />
+                        </form>
+                    {% endif %}
+                    {% if (is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user)) and package.abandoned %}
+                        <form class="pull-right action un-abandon" action="{{ path('unabandon_package', {name: package.name}) }}">
+                            <input class="btn btn-default" type="submit" value="Un-abandon" />
+                        </form>
+                    {% endif %}
+                </div>
+            </section>
 
-            {% if is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user) %}
-                <form class="action" action="{{ path("edit_package", {name: package.name}) }}">
-                    <input type="submit" value="Edit" />
-                </form>
-            {% endif %}
-            {% if is_granted('ROLE_UPDATE_PACKAGES') or package.maintainers.contains(app.user) %}
-                <form class="force-update action" action="{{ path('update_package', {name: package.name}) }}" method="POST">
-                    <input type="hidden" name="_method" value="PUT" />
-                    <input type="hidden" name="update" value="1" />
-                    <input type="submit" value="Force Update" />
-                </form>
-            {% endif %}
-            {% if deleteForm is defined %}
-                <form class="delete action" action="{{ path('delete_package', {name: package.name}) }}" method="POST">
-                    <input type="hidden" name="_method" value="DELETE" />
-                    {{ form_widget(deleteForm._token) }}
-                    <input type="submit" value="Delete" />
-                </form>
-            {% endif %}
-            {% if (is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user)) and not package.abandoned %}
-                <form class="action abandon" action="{{ path('abandon_package', {name: package.name}) }}">
-                    <input type="submit" value="Abandon" />
-                </form>
-            {% endif %}
-            {% if (is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user)) and package.abandoned %}
-                <form class="action un-abandon" action="{{ path('unabandon_package', {name: package.name}) }}">
-                    <input type="submit" value="Un-abandon" />
-                </form>
-            {% endif %}
-            <h1>
-                {% if is_favorite is defined %}
-                    <i class="mark-favorite icon-star{% if not is_favorite %}-empty{% endif %}" data-remove-url="{{ path('user_remove_fav', {name: app.user.username, package: package.name}) }}" data-add-url="{{ path('user_add_fav', {name: app.user.username}) }}" data-package="{{ package.name }}"></i>
-                {% endif %}
-                <a href="{{ path("view_vendor", {"vendor": package.vendor}) }}">{{ package.vendor }}/</a>{{ package.packageName }}
-                <a id="copy" data-clipboard-text="{{ package.name }}" title="Copy to clipboard"><i class="icon-copy"></i></a>
-            </h1>
             {% if version and version.tags|length %}
                 <p class="tags">
                     {%- for tag in version.tags -%}
@@ -62,14 +71,14 @@
 
             {% if not package.autoUpdated and app.user and (package.maintainers.contains(app.user) or is_granted('ROLE_UPDATE_PACKAGES')) %}
                 {% if "github.com" in package.repository %}
-                    <p class="warning">This package is not auto-updated. Please set up the <a href="{{ path('fos_user_profile_show') }}">GitHub Service Hook</a> for Packagist so that it gets updated whenever you push!</p>
+                    <div class="alert alert-danger">This package is not auto-updated. Please set up the <a href="{{ path('fos_user_profile_show') }}">GitHub Service Hook</a> for Packagist so that it gets updated whenever you push!</div>
                 {% elseif "bitbucket.org" in package.repository %}
-                    <p class="warning">This package is not auto-updated. Please set up the <a href="{{ path('fos_user_profile_show') }}">BitBucket POST Service</a> for Packagist so that it gets updated whenever you push!</p>
+                    <div class="alert alert-danger">This package is not auto-updated. Please set up the <a href="{{ path('fos_user_profile_show') }}">BitBucket POST Service</a> for Packagist so that it gets updated whenever you push!</div>
                 {% endif %}
             {% endif %}
 
             {% if package.abandoned %}
-                <p class="warning">
+                <div class="alert alert-warning">
                     This package is <strong>abandoned</strong> and no longer maintained.
                     {% if package.replacementPackage is not empty %}
                         The author suggests using the <a href="{{ path('view_package', {name: package.replacementPackage}) }}">{{ package.replacementPackage }}</a> package instead.
@@ -79,12 +88,12 @@
                             <a href="{{ path('abandon_package', {name: package.name}) }}">Suggest a replacement.</a>
                         {% endif %}
                     {% endif %}
-                </p>
+                </div>
             {% endif %}
             {% if package.updateFailureNotified
                 and app.user and (package.maintainers.contains(app.user) or is_granted('ROLE_UPDATE_PACKAGES'))
             %}
-                <p class="warning">This package is in a broken state and will not update anymore. Some branches contain invalid data and until you fix them the entire package is frozen. Click "Force Update" above to see details.</p>
+                <div class="alert alert-danger">This package is in a broken state and will not update anymore. Some branches contain invalid data and until you fix them the entire package is frozen. Click "Force Update" above to see details.</div>
             {% endif %}
 
             <p class="downloads">

+ 26 - 22
src/Packagist/WebBundle/Resources/views/macros.html.twig

@@ -6,35 +6,39 @@
             {% else %}
                 {% set packageUrl = path('view_providers', { 'name' : package.name }) %}
             {% endif %}
-            <li data-url="{{ packageUrl }}">
-                <h4 class="font-bold">
-                    {% if meta %}
-                        <span class="metadata pull-right">
-                            <i class="icon-box"></i> {{ meta.downloads[package.id]|default(0)|number_format(0, '.', ' ') }}
-                            <i class="glyphicon glyphicon-star"></i> {{ meta.favers[package.id]|number_format(0, '.', ' ') }}
-                        </span>
+            <li data-url="{{ packageUrl }}" class="row">
+                <div class="col-sm-9 col-lg-10">
+                    <h4 class="font-bold">
+                        <a href="{{ packageUrl }}">{{ package.name }}</a>
+                        {% if package.id is not numeric or package.name == 'nelmio/alice' %}
+                            <small>(Virtual Package)</small>
+                        {% endif %}
+                        {% if showAutoUpdateWarning and not package.autoUpdated %}
+                            <small>(Not Auto-Updated)</small>
+                        {% endif %}
+                    </h4>
+                    {% if package.description is defined and package.description %}
+                        <p>{{ package.description }}</p>
                     {% endif %}
-                    <a href="{{ packageUrl }}">{{ package.name }}</a>
-                    {% if package.id is not numeric %}
-                        <small>(virtual package)</small>
+                    {% if package.abandoned is defined and package.abandoned %}
+                        <p class="abandoned">
+                            <i class="glyphicon glyphicon-exclamation-sign"></i> Abandoned! {% if package.replacementPackage %}See <a href="{{ path('view_package', {name: package.replacementPackage}) }}">{{ package.replacementPackage }}</a>{% endif %}
+                        </p>
                     {% endif %}
-                    {% if showAutoUpdateWarning and not package.autoUpdated %}
-                        <small>[Not auto-updated]</small>
+                </div>
+                <div class="col-sm-3 col-lg-2">
+                    {% if meta %}
+                        <p class="metadata">
+                            <span class="metadata-block"><i class="glyphicon glyphicon-arrow-down"></i> {{ meta.downloads[package.id]|default(0)|number_format(0, '.', '&#8201;')|raw }}</span>
+                            <span class="metadata-block"><i class="glyphicon glyphicon-star"></i> {{ meta.favers[package.id]|number_format(0, '.', '&#8201;')|raw }}</span>
+                        </p>
                     {% endif %}
-                </h4>
-                {% if package.abandoned is defined and package.abandoned %}
-                    <span class="abandoned">
-                        <i class="glyphicon glyphicon-warning-sign"></i> Abandoned! {% if package.replacementPackage %}Use: <a href="{{ path('view_package', {name: package.replacementPackage}) }}">{{ package.replacementPackage }}</a>{% endif %}
-                    </span>
-                {% endif %}
-                {% if package.description is defined and package.description %}
-                    <p>{{ package.description }}</p>
-                {% endif %}
+                </div>
             </li>
         {% endfor %}
 
         {% if paginate is defined and paginate and packages.haveToPaginate() %}
-            {{ pagerfanta(packages, 'default', {'proximity': 2}) }}
+            {{ pagerfanta(packages, 'twitter_bootstrap', {'proximity': 2}) }}
         {% endif %}
     </ul>
 {% endmacro %}