Basic email template for notifications #96
1
.gitmodules
vendored
1
.gitmodules
vendored
@ -1,3 +1,4 @@
|
|||||||
[submodule "assets_shared"]
|
[submodule "assets_shared"]
|
||||||
path = assets_shared
|
path = assets_shared
|
||||||
url = https://projects.blender.org/infrastructure/web-assets.git
|
url = https://projects.blender.org/infrastructure/web-assets.git
|
||||||
|
branch = v2
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<div class="ext-detail-tagline">
|
<div class="ext-detail-tagline">
|
||||||
<a href="{{ extension.get_absolute_url }}">{{ extension.name }}</a>
|
<a href="{{ extension.get_absolute_url }}">{{ extension.name }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ext-detail-authors ml-3">
|
<div class="ext-detail-authors ms-3">
|
||||||
<a href="{% url 'extensions:by-type' type_slug=extension.type_slug %}">
|
<a href="{% url 'extensions:by-type' type_slug=extension.type_slug %}">
|
||||||
{{ extension.get_type_display }}
|
{{ extension.get_type_display }}
|
||||||
</a>
|
</a>
|
||||||
@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
{% block hero_tabs %}
|
{% block hero_tabs %}
|
||||||
<nav class="hero-tabs">
|
<nav class="hero-tabs">
|
||||||
<span class="ml-auto"></span>
|
<span class="ms-auto"></span>
|
||||||
|
|
||||||
<div class="btn-row mb-1">
|
<div class="btn-row mb-1">
|
||||||
{% if request.user.is_staff %}
|
{% if request.user.is_staff %}
|
||||||
@ -88,7 +88,7 @@
|
|||||||
<div class="dl-row">
|
<div class="dl-row">
|
||||||
<div class="dl-col">
|
<div class="dl-col">
|
||||||
<dt>Status</dt>
|
<dt>Status</dt>
|
||||||
<dd>{% include "common/components/status.html" with class="d-block" %}</dd>
|
<dd>{% include "common/components/status.html" %}</dd>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dl-row">
|
<div class="dl-row">
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 9d428a82a5b51c1eec99639f3baebeac3b1f93f9
|
Subproject commit af61a962e1a30898279b4efdbb07a2dcb230a257
|
@ -5,7 +5,7 @@ function galleriaCloneFirstItem() {
|
|||||||
let firstGalleriaItem = galleriaCarrousel.firstElementChild.cloneNode(true);
|
let firstGalleriaItem = galleriaCarrousel.firstElementChild.cloneNode(true);
|
||||||
firstGalleriaItem.classList.remove('js-galleria-item-preview', 'is-active');
|
firstGalleriaItem.classList.remove('js-galleria-item-preview', 'is-active');
|
||||||
firstGalleriaItem.classList.add('js-expand-on-click');
|
firstGalleriaItem.classList.add('js-expand-on-click');
|
||||||
firstGalleriaItem.id = 'galleria-item-large';
|
firstGalleriaItem.id = 'galleria-item-lg';
|
||||||
|
|
||||||
document.getElementById("galleria-container").prepend(firstGalleriaItem);
|
document.getElementById("galleria-container").prepend(firstGalleriaItem);
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@ function galleriaCloneFirstItem() {
|
|||||||
|
|
||||||
function galleriaSetLargePreview(item) {
|
function galleriaSetLargePreview(item) {
|
||||||
let previewsContainer = document.getElementById('galleria-items');
|
let previewsContainer = document.getElementById('galleria-items');
|
||||||
let previewLarge = document.getElementById('galleria-item-large');
|
let previewLarge = document.getElementById('galleria-item-lg');
|
||||||
let thumbnails = document.getElementsByClassName("js-galleria-item-preview");
|
let thumbnails = document.getElementsByClassName("js-galleria-item-preview");
|
||||||
[].forEach.call(thumbnails, function(el) {
|
[].forEach.call(thumbnails, function(el) {
|
||||||
el.classList.remove("is-active");
|
el.classList.remove("is-active");
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
z-index: 0
|
z-index: 0
|
||||||
|
|
||||||
> li
|
> li
|
||||||
--border-color: var(--box-background-color)
|
--border-color: var(--box-bg-color)
|
||||||
position: relative
|
position: relative
|
||||||
|
|
||||||
&:first-child
|
&:first-child
|
||||||
@ -16,7 +16,7 @@
|
|||||||
&:last-child
|
&:last-child
|
||||||
/* Remove bottom half of the vertical line for last item. */
|
/* Remove bottom half of the vertical line for last item. */
|
||||||
.comment-card:before
|
.comment-card:before
|
||||||
height: calc(50% - 1rem)
|
height: calc(50% - var(--spacer))
|
||||||
.activity-status-change:before
|
.activity-status-change:before
|
||||||
height: calc(50% + var(--border-width))
|
height: calc(50% + var(--border-width))
|
||||||
|
|
||||||
@ -50,21 +50,25 @@
|
|||||||
left: var(--border-width)
|
left: var(--border-width)
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 50%
|
top: 50%
|
||||||
width: 2rem
|
width: calc(var(--spacer) * 2)
|
||||||
z-index: -1
|
z-index: -1
|
||||||
|
|
||||||
|
.activity-icon
|
||||||
|
top: 1.2rem
|
||||||
|
|
||||||
.profile-avatar
|
.profile-avatar
|
||||||
border: var(--border-width) solid var(--border-color)
|
border: var(--border-width) solid var(--border-color)
|
||||||
background-color: var(--border-color)
|
background-color: var(--border-color)
|
||||||
|
|
||||||
.comment-card
|
.comment-card
|
||||||
&:after
|
&:after
|
||||||
top: 2rem
|
top: 3.2rem
|
||||||
|
|
||||||
.activity-icon
|
.activity-icon
|
||||||
top: 1.25rem
|
top: 2.2rem
|
||||||
|
|
||||||
.activity-status-change
|
.activity-status-change
|
||||||
color: var(--text-color-tertiary)
|
color: var(--color-text-tertiary)
|
||||||
|
|
||||||
.profile-avatar
|
.profile-avatar
|
||||||
+margin(3, right)
|
+margin(3, right)
|
||||||
@ -73,7 +77,7 @@
|
|||||||
left: 0
|
left: 0
|
||||||
|
|
||||||
strong
|
strong
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
|
|
||||||
.badge
|
.badge
|
||||||
border: none
|
border: none
|
||||||
@ -83,22 +87,22 @@
|
|||||||
&.activity-status-approved
|
&.activity-status-approved
|
||||||
.activity-icon
|
.activity-icon
|
||||||
border-color: var(--color-success)
|
border-color: var(--color-success)
|
||||||
box-shadow: 0 0 1rem var(--color-success-bg)
|
box-shadow: 0 0 var(--spacer) var(--color-success-bg)
|
||||||
color: var(--color-success-text)
|
color: var(--color-success-text)
|
||||||
|
|
||||||
.activity-icon
|
.activity-icon
|
||||||
align-items: center
|
align-items: center
|
||||||
background-color: var(--background-color)
|
background-color: var(--color-bg)
|
||||||
border-radius: 100%
|
border-radius: 100%
|
||||||
border: var(--border-width) solid var(--border-color)
|
border: var(--border-width) solid var(--border-color)
|
||||||
color: var(--text-color-tertiary)
|
color: var(--color-text-tertiary)
|
||||||
display: flex
|
display: flex
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
height: 1.5rem
|
height: var(--spacer-4)
|
||||||
justify-content: center
|
justify-content: center
|
||||||
left: -.66rem
|
left: -.66rem
|
||||||
position: absolute
|
position: absolute
|
||||||
width: 1.5rem
|
width: var(--spacer-4)
|
||||||
|
|
||||||
/* Comment form */
|
/* Comment form */
|
||||||
.comment-form
|
.comment-form
|
||||||
@ -112,9 +116,6 @@
|
|||||||
select
|
select
|
||||||
width: auto
|
width: auto
|
||||||
|
|
||||||
button[type="submit"]
|
|
||||||
min-width: 50%
|
|
||||||
|
|
||||||
textarea
|
textarea
|
||||||
height: calc(var(--spacer) * 8)
|
height: calc(var(--spacer) * 8)
|
||||||
max-height: 0
|
max-height: 0
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
|
.badge-card
|
||||||
|
+border-radius(lg)
|
||||||
|
border-bottom-left-radius: 0
|
||||||
|
border-bottom-right-radius: 0
|
||||||
|
display: flex
|
||||||
|
+padding(2, y)
|
||||||
|
|
||||||
a.badge-tag
|
a.badge-tag
|
||||||
--badge-color: var(--text-color-secondary)
|
--badge-color: var(--color-text-secondary)
|
||||||
--badge-bg: var(--text-color-tertiary)
|
--badge-bg: var(--color-text-tertiary)
|
||||||
|
|
||||||
background-color: transparent
|
background-color: transparent
|
||||||
text-decoration: none !important
|
text-decoration: none !important
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
background-color: transparent
|
background-color: transparent
|
||||||
border-color: var(--text-color)
|
border-color: var(--color-text)
|
||||||
color: var(--text-color)
|
color: var(--color-text)
|
||||||
|
|
||||||
.badge-tag
|
.badge-tag
|
||||||
font-size: var(--font-size-extra-small)
|
font-size: var(--fs-xs)
|
||||||
|
|
||||||
.badge-status
|
.badge-status
|
||||||
&-approved
|
&-approved
|
||||||
@ -24,10 +31,3 @@ a.badge-tag
|
|||||||
&-disabled-by-staff,
|
&-disabled-by-staff,
|
||||||
&-disabled-by-author
|
&-disabled-by-author
|
||||||
@extend .badge-secondary
|
@extend .badge-secondary
|
||||||
|
|
||||||
.card-badge
|
|
||||||
+border-radius(lg)
|
|
||||||
border-bottom-left-radius: 0
|
|
||||||
border-bottom-right-radius: 0
|
|
||||||
display: flex
|
|
||||||
+padding(2, y)
|
|
||||||
|
29
common/static/common/styles/_cards.sass
Normal file
29
common/static/common/styles/_cards.sass
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
.card
|
||||||
|
@extend .box
|
||||||
|
|
||||||
|
+media-sm
|
||||||
|
--cards-items-per-row: 2
|
||||||
|
|
||||||
|
+media-md
|
||||||
|
--cards-items-per-row: 3
|
||||||
|
|
||||||
|
+media-lg
|
||||||
|
--cards-items-per-row: 4
|
||||||
|
|
||||||
|
.cards-item-content
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
.crads-item-excerpt
|
||||||
|
line-height: calc(24 / 18)
|
||||||
|
|
||||||
|
.cards-item-extra
|
||||||
|
text-transform: none
|
||||||
|
|
||||||
|
.cards-item-extra-rating-stars
|
||||||
|
margin-bottom: .2rem
|
||||||
|
|
||||||
|
.stars
|
||||||
|
font-size: 1.4rem
|
||||||
|
|
||||||
|
.cards-item-title
|
||||||
|
+padding(0, y)
|
@ -11,33 +11,36 @@
|
|||||||
z-index: 0
|
z-index: 0
|
||||||
|
|
||||||
&:before
|
&:before
|
||||||
background-color: var(--box-background-color)
|
background-color: var(--box-bg-color)
|
||||||
border-radius: .25rem
|
border-radius: .4rem
|
||||||
content: ''
|
content: ''
|
||||||
display: block
|
display: block
|
||||||
height: 1rem
|
height: var(--spacer)
|
||||||
left: -.33rem
|
left: -.33rem
|
||||||
position: absolute
|
position: absolute
|
||||||
rotate: 45deg
|
rotate: 45deg
|
||||||
top: 1rem
|
top: var(--spacer)
|
||||||
width: 1rem
|
width: var(--spacer)
|
||||||
z-index: -1
|
z-index: -1
|
||||||
|
|
||||||
p:last-child
|
p:last-child
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
|
||||||
header
|
header
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
+margin(2, bottom)
|
+margin(2, bottom)
|
||||||
|
|
||||||
ul
|
ul
|
||||||
align-items: center
|
align-items: center
|
||||||
display: flex
|
display: flex
|
||||||
+list-unstyled
|
+list-unstyled
|
||||||
gap: 1rem
|
gap: var(--spacer)
|
||||||
margin: 0
|
margin: 0
|
||||||
|
|
||||||
|
li
|
||||||
|
line-height: var(--lh-sm)
|
||||||
|
|
||||||
aside
|
aside
|
||||||
+margin(2, top)
|
+margin(2, top)
|
||||||
|
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
|
\:root
|
||||||
|
--lh-sm: 2.4rem
|
||||||
|
|
||||||
.hero.extension-detail
|
.hero.extension-detail
|
||||||
--hero-max-height: 0
|
--hero-max-height: 0
|
||||||
--hero-min-height: 240px
|
--hero-min-height: 24.0rem
|
||||||
--font-size-hero-title: clamp(3rem, 4vw + 1rem, 48px)
|
--fs-hero-title: clamp(4.8rem, 4vw + 1.6rem, 4.8rem)
|
||||||
--font-size-large: 18px
|
--fs-lg: 1.8rem
|
||||||
--border-width: 2px
|
--border-width: .2rem
|
||||||
--hero-background-color: hsl(213, 10%, 14%)
|
--hero-bg-color: hsl(213, 10%, 14%)
|
||||||
|
|
||||||
background-color: var(--hero-background-color)
|
background-color: var(--hero-bg-color)
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%233e4248' fill-opacity='0.21'%3E%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%233e4248' fill-opacity='0.21'%3E%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")
|
||||||
background-size: 40px
|
background-size: 4.0rem
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
overflow: initial
|
overflow: initial
|
||||||
text-shadow: none
|
text-shadow: none
|
||||||
@ -24,10 +27,10 @@
|
|||||||
|
|
||||||
.hero-overlay
|
.hero-overlay
|
||||||
background-color: transparent
|
background-color: transparent
|
||||||
background-image: linear-gradient(0deg, var(--background-color), hsla(213, 10%, 14%, 0))
|
background-image: linear-gradient(0deg, var(--color-bg), hsla(213, 10%, 14%, 0))
|
||||||
|
|
||||||
&.extension-review
|
&.extension-review
|
||||||
--hero-min-height: 210px
|
--hero-min-height: 21.0rem
|
||||||
|
|
||||||
.ext-detail-download-danger
|
.ext-detail-download-danger
|
||||||
background-color: var(--color-danger-bg)
|
background-color: var(--color-danger-bg)
|
||||||
@ -42,8 +45,8 @@
|
|||||||
@extend .alert
|
@extend .alert
|
||||||
@extend .alert-danger
|
@extend .alert-danger
|
||||||
border-radius: 0
|
border-radius: 0
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
+font-weight-bold
|
+fw-bold
|
||||||
+padding(1, y)
|
+padding(1, y)
|
||||||
text-align: center
|
text-align: center
|
||||||
|
|
||||||
@ -54,17 +57,17 @@
|
|||||||
color: var(--color-warning-text);
|
color: var(--color-warning-text);
|
||||||
|
|
||||||
.hero-breadcrumbs
|
.hero-breadcrumbs
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
|
|
||||||
a
|
a
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
display: inline-block
|
display: inline-block
|
||||||
+padding(2)
|
+padding(2)
|
||||||
|
|
||||||
.ext-detail-name
|
.ext-detail-name
|
||||||
font-size: var(--font-size-title-massive)
|
font-size: var(--fs-title-massive)
|
||||||
+font-weight-title
|
+fw-title
|
||||||
line-height: var(--font-size-title-massive)
|
line-height: var(--fs-title-massive)
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
|
||||||
.ext-detail-info-authors
|
.ext-detail-info-authors
|
||||||
@ -72,7 +75,7 @@
|
|||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
|
|
||||||
.ext-detail-authors
|
.ext-detail-authors
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
|
|
||||||
.ext-detail-tagline
|
.ext-detail-tagline
|
||||||
+margin(2, bottom)
|
+margin(2, bottom)
|
||||||
@ -81,9 +84,12 @@
|
|||||||
+padding(4)
|
+padding(4)
|
||||||
+style-rich-text
|
+style-rich-text
|
||||||
|
|
||||||
|
pre
|
||||||
|
+margin(3, bottom)
|
||||||
|
|
||||||
.ext-detail-info
|
.ext-detail-info
|
||||||
dd
|
dd
|
||||||
color: var(--text-color)
|
color: var(--color-text)
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
text-overflow: ellipsis
|
text-overflow: ellipsis
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
@ -93,8 +99,9 @@
|
|||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
|
||||||
dt
|
dt
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
|
line-height: calc(24 / 14)
|
||||||
|
|
||||||
dd
|
dd
|
||||||
font-family: var(--font-family-body)
|
font-family: var(--font-family-body)
|
||||||
@ -108,7 +115,7 @@
|
|||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
color: var(--text-color-primary)
|
color: var(--color-text-primary)
|
||||||
|
|
||||||
.dl-col
|
.dl-col
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
@ -134,10 +141,10 @@
|
|||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
strong
|
strong
|
||||||
font-size: var(--font-size-large)
|
font-size: var(--fs-lg)
|
||||||
|
|
||||||
i
|
i
|
||||||
font-size: var(--font-size-large)
|
font-size: var(--fs-lg)
|
||||||
+margin(3, right)
|
+margin(3, right)
|
||||||
|
|
||||||
.ext-detail-download
|
.ext-detail-download
|
||||||
@ -145,7 +152,7 @@
|
|||||||
+padding(2, y)
|
+padding(2, y)
|
||||||
|
|
||||||
.btn-accent
|
.btn-accent
|
||||||
box-shadow: 2px 5px 5px rgba(0,82,255,.102), 1px 10px 15px rgba(0,82,255,.102), 2px 10px 30px rgba(0,82,255,.349)
|
box-shadow: .2rem .8rem .8rem rgba(0,82,255,.102), 1.6rem 1.0rem 1.8rem rgba(0,82,255,.102), 3.2rem 1.0rem 3.2rem rgba(0,82,255,.349)
|
||||||
|
|
||||||
.btn-install-drag,
|
.btn-install-drag,
|
||||||
.btn-install-drag:active
|
.btn-install-drag:active
|
||||||
@ -160,134 +167,21 @@
|
|||||||
summary
|
summary
|
||||||
.date
|
.date
|
||||||
+margin(2, left)
|
+margin(2, left)
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
+font-weight-normal
|
+fw-normal
|
||||||
|
|
||||||
.cards-list
|
|
||||||
+media-sm
|
|
||||||
--cards-list-items-per-row: 2
|
|
||||||
+media-md
|
|
||||||
--cards-list-items-per-row: 3
|
|
||||||
+media-lg
|
|
||||||
--cards-list-items-per-row: 4
|
|
||||||
|
|
||||||
.ext-card
|
|
||||||
+box-card
|
|
||||||
display: flex
|
|
||||||
flex-direction: column
|
|
||||||
height: 100%
|
|
||||||
overflow: hidden
|
|
||||||
transition: box-shadow ease-in-out 1s
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
box-shadow: 10px 10px 20px 0px rgba(0, 0, 0, .04), -10px 0 20px 0px rgba(0, 0, 0, .04)
|
|
||||||
|
|
||||||
&.is-background-blur
|
|
||||||
background-color: hsl(213, 10%, 21%)
|
|
||||||
border: thin solid hsl(213, 10%, 20%)
|
|
||||||
position: relative
|
|
||||||
|
|
||||||
.ext-card-body
|
|
||||||
--text-color-secondary: hsla(213, 40%, 90%, .6)
|
|
||||||
|
|
||||||
border-bottom-left-radius: var(--border-radius-lg)
|
|
||||||
border-bottom-right-radius: var(--border-radius-lg)
|
|
||||||
+padding(1, top)
|
|
||||||
mix-blend-mode: screen
|
|
||||||
position: relative
|
|
||||||
z-index: 1
|
|
||||||
|
|
||||||
&:has(.ext-card-admin)
|
|
||||||
.ext-card-body
|
|
||||||
border-radius: 0
|
|
||||||
|
|
||||||
.ext-card-thumbnail-img
|
|
||||||
-webkit-mask-image: -webkit-gradient(linear, left 60%, left bottom, from(rgba(0,0,0,1)), to(rgba(0,0,0,0)))
|
|
||||||
|
|
||||||
.ext-card-thumbnail:hover
|
|
||||||
&+.ext-card-body .ext-card-title
|
|
||||||
color: var(--text-color-primary)
|
|
||||||
|
|
||||||
&.ext-card-row
|
|
||||||
flex-direction: row
|
|
||||||
+margin(3, bottom)
|
|
||||||
|
|
||||||
.ext-card-thumbnail
|
|
||||||
--card-thumbnail-width: 240px
|
|
||||||
border-top-right-radius: 0
|
|
||||||
border-bottom-left-radius: var(--border-radius-lg)
|
|
||||||
height: 100%
|
|
||||||
|
|
||||||
img
|
|
||||||
border-top-right-radius: 0
|
|
||||||
border-bottom-left-radius: var(--border-radius-lg)
|
|
||||||
|
|
||||||
.ext-blender-version
|
|
||||||
display: inline-block
|
|
||||||
|
|
||||||
.ext-card-thumbnail-blur
|
|
||||||
bottom: 0
|
|
||||||
filter: blur(50px)
|
|
||||||
left: 0
|
|
||||||
position: absolute
|
|
||||||
right: 0
|
|
||||||
transform: scale(1.25)
|
|
||||||
top: 0
|
|
||||||
z-index: 0
|
|
||||||
opacity: .5
|
|
||||||
|
|
||||||
.ext-card-thumbnail
|
|
||||||
--card-thumbnail-width: 100%
|
|
||||||
|
|
||||||
align-items: center
|
|
||||||
border-top-left-radius: var(--border-radius-lg)
|
|
||||||
border-top-right-radius: var(--border-radius-lg)
|
|
||||||
display: block
|
|
||||||
justify-content: center
|
|
||||||
max-width: var(--card-thumbnail-width)
|
|
||||||
overflow: hidden
|
|
||||||
|
|
||||||
.ext-card-thumbnail-img
|
|
||||||
background-position: center
|
|
||||||
background-size: cover
|
|
||||||
+make-aspect-ratio('16x9')
|
|
||||||
transition: transform ease-out var(--transition-speed)
|
|
||||||
|
|
||||||
.ext-card-body
|
|
||||||
display: flex
|
|
||||||
flex: 1
|
|
||||||
flex-direction: column
|
|
||||||
justify-content: space-between
|
|
||||||
+padding(3)
|
|
||||||
|
|
||||||
p
|
|
||||||
line-height: 1.2
|
|
||||||
|
|
||||||
.ext-card-title
|
|
||||||
font-size: var(--font-size-large)
|
|
||||||
+margin(3, bottom)
|
|
||||||
transition: color var(--transition-speed)
|
|
||||||
|
|
||||||
a
|
|
||||||
text-decoration: none
|
|
||||||
|
|
||||||
.ext-list-details
|
.ext-list-details
|
||||||
@extend .list-inline
|
@extend .list-inline
|
||||||
|
|
||||||
align-items: center
|
align-items: center
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
|
line-height: var(--lh-sm)
|
||||||
margin: auto 0 0 0
|
margin: auto 0 0 0
|
||||||
|
|
||||||
&+.ext-list-details
|
&+.ext-list-details
|
||||||
+margin(2, top)
|
+margin(2, top)
|
||||||
|
|
||||||
.ext-card-tags
|
|
||||||
display: flex
|
|
||||||
flex-wrap: wrap
|
|
||||||
gap: .25rem
|
|
||||||
justify-content: flex-start
|
|
||||||
|
|
||||||
/* Show only on row list view.*/
|
/* Show only on row list view.*/
|
||||||
.ext-blender-version
|
.ext-blender-version
|
||||||
display: none
|
display: none
|
||||||
@ -295,19 +189,6 @@
|
|||||||
.ext-edit-field-row
|
.ext-edit-field-row
|
||||||
+margin(2, top)
|
+margin(2, top)
|
||||||
|
|
||||||
.ext-card-admin
|
|
||||||
align-items: center
|
|
||||||
background-color: hsla(213, 80%, 1%, .33)
|
|
||||||
border-bottom-left-radius: var(--border-radius-lg)
|
|
||||||
border-bottom-right-radius: var(--border-radius-lg)
|
|
||||||
border-top: var(--border-width) solid var(--border-color)
|
|
||||||
display: flex
|
|
||||||
justify-content: space-between
|
|
||||||
z-index: 1
|
|
||||||
|
|
||||||
dd
|
|
||||||
font-family: var(--font-body)
|
|
||||||
|
|
||||||
.previews-upload
|
.previews-upload
|
||||||
+box-card
|
+box-card
|
||||||
+padding(3)
|
+padding(3)
|
||||||
@ -316,27 +197,29 @@
|
|||||||
.previews-list
|
.previews-list
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
gap: .5rem
|
gap: .8rem
|
||||||
|
|
||||||
.previews-list-item
|
.previews-list-item
|
||||||
--preview-thumbnail-max-size: 180px
|
--preview-thumbnail-max-size: calc(12.4rem * 16 / 9)
|
||||||
|
|
||||||
align-items: center
|
align-items: start
|
||||||
background-color:
|
background-color:
|
||||||
border-radius: var(--border-radius-lg)
|
border-radius: var(--border-radius-lg)
|
||||||
border: var(--border-width) solid var(--border-color)
|
border: var(--border-width) solid var(--border-color)
|
||||||
display: flex
|
display: flex
|
||||||
+padding(1, y)
|
+padding(2, y)
|
||||||
|
|
||||||
.previews-list-item-thumbnail
|
.previews-list-item-thumbnail
|
||||||
margin: 0
|
margin: 0
|
||||||
|
+margin(2, y)
|
||||||
width: var(--preview-thumbnail-max-size)
|
width: var(--preview-thumbnail-max-size)
|
||||||
|
|
||||||
.previews-list-item-thumbnail-img
|
.previews-list-item-thumbnail-img
|
||||||
background-color: var(--background-color)
|
background-color: var(--color-bg)
|
||||||
background-position: center
|
background-position: center
|
||||||
background-size: cover
|
background-size: cover
|
||||||
border-radius: var(--border-radius)
|
border-radius: var(--border-radius)
|
||||||
|
height: 12.4rem
|
||||||
+make-aspect-ratio('16x9')
|
+make-aspect-ratio('16x9')
|
||||||
|
|
||||||
.details
|
.details
|
||||||
@ -344,7 +227,8 @@
|
|||||||
flex: 1
|
flex: 1
|
||||||
|
|
||||||
label
|
label
|
||||||
font-size: var(--font-size-small)
|
font-size: var(--fs-sm)
|
||||||
|
line-height: var(--lh-sm)
|
||||||
|
|
||||||
ul
|
ul
|
||||||
+list-unstyled
|
+list-unstyled
|
||||||
@ -365,7 +249,7 @@
|
|||||||
|
|
||||||
.form-control
|
.form-control
|
||||||
&[type="file"]
|
&[type="file"]
|
||||||
font-size: var(--font-size-extra-small)
|
font-size: var(--fs-xs)
|
||||||
max-width: 50%
|
max-width: 50%
|
||||||
|
|
||||||
.ext-version-history
|
.ext-version-history
|
||||||
@ -374,49 +258,52 @@
|
|||||||
|
|
||||||
ul
|
ul
|
||||||
@extend .list-inline
|
@extend .list-inline
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
+font-weight-normal
|
+fw-normal
|
||||||
gap: 0 1rem
|
gap: 0 1.6rem
|
||||||
margin: 0
|
margin: 0
|
||||||
+margin(3, right)
|
+margin(3, right)
|
||||||
|
|
||||||
.blender-version
|
.blender-version
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
+font-weight-normal
|
+fw-normal
|
||||||
+margin(3, left)
|
+margin(3, left)
|
||||||
|
|
||||||
details[open]
|
details
|
||||||
.show-on-collapse
|
padding: 0
|
||||||
display: none
|
|
||||||
|
&[open]
|
||||||
|
.show-on-collapse
|
||||||
|
display: none
|
||||||
|
|
||||||
.ext-detail-info
|
.ext-detail-info
|
||||||
.ext-detail-permissions
|
.ext-detail-permissions
|
||||||
strong
|
strong
|
||||||
font-size: var(--font-size-normal)
|
font-size: var(--fs-normal)
|
||||||
|
|
||||||
small
|
small
|
||||||
display: block
|
display: block
|
||||||
|
|
||||||
i
|
i
|
||||||
font-size: var(--font-size-normal)
|
font-size: var(--fs-normal)
|
||||||
+margin(2, right)
|
+margin(2, right)
|
||||||
|
|
||||||
/* Settings */
|
/* Settings */
|
||||||
.settings
|
.settings
|
||||||
.form-control
|
.form-control
|
||||||
&[disabled]
|
&[disabled]
|
||||||
--input-bg-color: var(--background-color)
|
--input-color-bg: var(--color-bg)
|
||||||
|
|
||||||
background-color: var(--input-bg-color)
|
background-color: var(--input-color-bg)
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
--input-bg-color-hover: var(--input-bg-color)
|
--input-color-bg-hover: var(--input-color-bg)
|
||||||
|
|
||||||
cursor: not-allowed
|
cursor: not-allowed
|
||||||
|
|
||||||
& + i.i-lock
|
& + i.i-lock
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
position: absolute
|
position: absolute
|
||||||
right: var(--spacer)
|
right: var(--spacer)
|
||||||
|
|
||||||
@ -430,7 +317,7 @@
|
|||||||
+margin(2, right)
|
+margin(2, right)
|
||||||
|
|
||||||
.ext-review-list
|
.ext-review-list
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
|
|
||||||
th
|
th
|
||||||
+padding(3, x)
|
+padding(3, x)
|
||||||
@ -440,7 +327,7 @@
|
|||||||
transition: background-color var(--transition-speed-fast)
|
transition: background-color var(--transition-speed-fast)
|
||||||
|
|
||||||
a
|
a
|
||||||
color: var(--text-color)
|
color: var(--color-text)
|
||||||
+padding(1, y)
|
+padding(1, y)
|
||||||
padding-inline: 0 !important
|
padding-inline: 0 !important
|
||||||
|
|
||||||
@ -456,3 +343,36 @@
|
|||||||
.ext-review-list-activity
|
.ext-review-list-activity
|
||||||
display: flex
|
display: flex
|
||||||
+padding(0, x)
|
+padding(0, x)
|
||||||
|
|
||||||
|
.rating-form
|
||||||
|
select
|
||||||
|
color: var(--color-warning)
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&:hover,
|
||||||
|
&:focus
|
||||||
|
color: var(--color-warning)
|
||||||
|
|
||||||
|
// TODO: consider adding component boxed nav generic to web-assets, and make variants on top of that
|
||||||
|
.nav-pills
|
||||||
|
@extend .dropdown-menu
|
||||||
|
|
||||||
|
box-shadow: none
|
||||||
|
display: block
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
.nav-pills-item
|
||||||
|
@extend .dropdown-item
|
||||||
|
|
||||||
|
+margin(1, bottom)
|
||||||
|
|
||||||
|
&.active
|
||||||
|
background-color: var(--color-accent-bg)
|
||||||
|
|
||||||
|
&:last-child
|
||||||
|
+margin(0, bottom)
|
||||||
|
|
||||||
|
.nav-pills-divider
|
||||||
|
@extend .dropdown-divider
|
||||||
|
|
||||||
|
+margin(0, top)
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
.form-check-input,
|
||||||
|
.form-check-label
|
||||||
|
&:hover
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.form-check-input
|
||||||
|
height: var(--spacer-4)
|
||||||
|
|
||||||
|
.form-check-label
|
||||||
|
+margin(2, left)
|
||||||
|
|
||||||
|
.form-control
|
||||||
|
&[type="file"]
|
||||||
|
height: calc(var(--spacer) * 2.5)
|
||||||
|
|
||||||
/* Override Tagger's styling. */
|
/* Override Tagger's styling. */
|
||||||
.was-validated .form-control:invalid,
|
.was-validated .form-control:invalid,
|
||||||
.form-control.is-invalid
|
.form-control.is-invalid
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
.galleria-container
|
.galleria-container
|
||||||
--extension-thumbnail-width: 140px
|
--extension-thumbnail-width: 14.0rem
|
||||||
|
|
||||||
background-color: var(--background-color-secondary)
|
background-color: var(--color-bg-secondary)
|
||||||
border-radius: var(--border-radius-lg)
|
border-radius: var(--border-radius-lg)
|
||||||
+padding(2)
|
+padding(2)
|
||||||
|
|
||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
.galleria-items
|
.galleria-items
|
||||||
display: flex
|
display: flex
|
||||||
gap: .5rem
|
gap: var(--spacer-2)
|
||||||
overflow-x: auto
|
overflow-x: auto
|
||||||
+padding(2, top)
|
+padding(2, top)
|
||||||
scroll-behavior: smooth
|
scroll-behavior: smooth
|
||||||
@ -25,7 +25,7 @@
|
|||||||
display: none
|
display: none
|
||||||
|
|
||||||
&::-webkit-scrollbar
|
&::-webkit-scrollbar
|
||||||
height: 10px
|
height: 1.0rem
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb
|
&::-webkit-scrollbar-thumb
|
||||||
@ -33,7 +33,7 @@
|
|||||||
border-radius: 999em
|
border-radius: 999em
|
||||||
|
|
||||||
&::-webkit-scrollbar-track
|
&::-webkit-scrollbar-track
|
||||||
background-color: hsl(var(--background-color-h), var(--background-color-s), 80%)
|
background-color: hsl(var(--color-bg-h), var(--color-bg-s), 80%)
|
||||||
|
|
||||||
.galleria-item
|
.galleria-item
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
.galleria-item-type-video
|
.galleria-item-type-video
|
||||||
&::after
|
&::after
|
||||||
font-size: 2rem
|
font-size: calc(var(--spacer) * 2)
|
||||||
|
|
||||||
.galleria-item
|
.galleria-item
|
||||||
+border-radius
|
+border-radius
|
||||||
@ -69,14 +69,14 @@
|
|||||||
transform: translate(-50%, -50%)
|
transform: translate(-50%, -50%)
|
||||||
width: initial
|
width: initial
|
||||||
height: initial
|
height: initial
|
||||||
gap: 1rem
|
gap: var(--spacer)
|
||||||
|
|
||||||
|
|
||||||
&.is-active
|
&.is-active
|
||||||
background-color: var(--color-primary)
|
background-color: var(--color-accent)
|
||||||
|
|
||||||
img
|
img
|
||||||
clip-path: inset(0.2rem 0.2rem 0.2rem 0.2rem)
|
clip-path: inset(.2rem .2rem .2rem .2rem)
|
||||||
|
|
||||||
img
|
img
|
||||||
clip-path: inset(0 0 0 0)
|
clip-path: inset(0 0 0 0)
|
||||||
@ -92,7 +92,7 @@
|
|||||||
color: white
|
color: white
|
||||||
content: '\e83e'
|
content: '\e83e'
|
||||||
font-family: 'fontutti'
|
font-family: 'fontutti'
|
||||||
font-size: 4rem
|
font-size: 5.6rem
|
||||||
left: 50%
|
left: 50%
|
||||||
top: 50%
|
top: 50%
|
||||||
pointer-events: none
|
pointer-events: none
|
||||||
@ -120,7 +120,7 @@
|
|||||||
background: transparent
|
background: transparent
|
||||||
border: none
|
border: none
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
font-size: 4rem
|
font-size: 5.6rem
|
||||||
height: 100vh
|
height: 100vh
|
||||||
max-width: 200px
|
max-width: 200px
|
||||||
opacity: .6
|
opacity: .6
|
||||||
@ -143,7 +143,7 @@
|
|||||||
|
|
||||||
&.btn-close
|
&.btn-close
|
||||||
fill: white
|
fill: white
|
||||||
font-size: 2rem
|
font-size: 3.2rem
|
||||||
height: 20vh
|
height: 20vh
|
||||||
max-height: 80px
|
max-height: 80px
|
||||||
max-width: 80px
|
max-width: 80px
|
||||||
@ -174,9 +174,9 @@
|
|||||||
|
|
||||||
.indicator
|
.indicator
|
||||||
background-color: rgba(black, .5)
|
background-color: rgba(black, .5)
|
||||||
bottom: 1rem
|
bottom: var(--spacer)
|
||||||
color: white
|
color: white
|
||||||
+font-weight-bold
|
+fw-bold
|
||||||
min-width: 3ch
|
min-width: 3ch
|
||||||
+padding(2, x)
|
+padding(2, x)
|
||||||
position: absolute
|
position: absolute
|
||||||
@ -184,10 +184,10 @@
|
|||||||
text-align: right
|
text-align: right
|
||||||
|
|
||||||
.caption
|
.caption
|
||||||
backdrop-filter: blur(25px)
|
backdrop-filter: blur(2.8rem)
|
||||||
background-color: rgba(black, .5)
|
background-color: rgba(black, .5)
|
||||||
border-radius: var(--border-radius)
|
border-radius: var(--border-radius)
|
||||||
bottom: 1rem
|
bottom: var(--spacer)
|
||||||
color: white
|
color: white
|
||||||
+font-weight(500)
|
+font-weight(500)
|
||||||
line-height: 1.5
|
line-height: 1.5
|
||||||
@ -195,7 +195,7 @@
|
|||||||
+padding(2, x)
|
+padding(2, x)
|
||||||
position: absolute
|
position: absolute
|
||||||
text-align: center
|
text-align: center
|
||||||
text-shadow: 1px 1px 0 black, 2px 2px 3px rgba(black, .5)
|
text-shadow: .1rem .1rem 0 black, .2rem .2rem rgba(black, .5)
|
||||||
|
|
||||||
body.is-galleria-active
|
body.is-galleria-active
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
&.is-flatpage
|
&.is-flatpage
|
||||||
--hero-max-height: 0
|
--hero-max-height: 0
|
||||||
--hero-min-height: 240px
|
--hero-min-height: 24.0rem
|
||||||
background: transparent
|
background: transparent
|
||||||
|
|
||||||
.hero-content
|
.hero-content
|
||||||
@ -23,7 +23,7 @@
|
|||||||
> a:not(.btn)
|
> a:not(.btn)
|
||||||
background-color: transparent
|
background-color: transparent
|
||||||
border-radius: 0
|
border-radius: 0
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
display: inline-block
|
display: inline-block
|
||||||
+padding(4, x)
|
+padding(4, x)
|
||||||
+padding(2, y)
|
+padding(2, y)
|
||||||
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
&::after
|
&::after
|
||||||
background-color: currentColor
|
background-color: currentColor
|
||||||
bottom: -1px
|
bottom: -.1rem
|
||||||
content: ''
|
content: ''
|
||||||
height: var(--border-width)
|
height: var(--border-width)
|
||||||
left: 0
|
left: 0
|
||||||
@ -48,7 +48,7 @@
|
|||||||
opacity: 1
|
opacity: 1
|
||||||
|
|
||||||
&.is-active
|
&.is-active
|
||||||
+font-weight-bold
|
+fw-bold
|
||||||
color: white
|
color: white
|
||||||
|
|
||||||
&::after
|
&::after
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
|
.dl-col
|
||||||
|
margin-bottom: -.1rem // Compensate border-bottom height
|
||||||
|
|
||||||
.dl-col-2
|
.dl-col-2
|
||||||
flex-grow: 2
|
flex-grow: 2
|
||||||
|
|
||||||
|
.dl-row
|
||||||
|
+padding(2, bottom)
|
||||||
|
|
||||||
|
&:first-child
|
||||||
|
+padding(0, top)
|
||||||
|
|
||||||
.list-filters
|
.list-filters
|
||||||
+box-card
|
+box-card
|
||||||
background-color: var(--background-color-tertiary)
|
background-color: var(--color-bg-tertiary)
|
||||||
+padding(3)
|
+padding(3)
|
||||||
|
|
||||||
h3
|
h3
|
||||||
border-bottom: var(--border-width) solid var(--border-color)
|
border-bottom: var(--border-width) solid var(--border-color)
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
+padding(2, bottom)
|
+padding(2, bottom)
|
||||||
|
|
||||||
ul
|
ul
|
||||||
@ -17,12 +26,12 @@
|
|||||||
|
|
||||||
li
|
li
|
||||||
&.is-active
|
&.is-active
|
||||||
color: var(--text-color-primary)
|
color: var(--color-text-primary)
|
||||||
+font-weight-bold
|
+fw-bold
|
||||||
|
|
||||||
a
|
a
|
||||||
display: block
|
display: block
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
color: var(--text-color-primary)
|
color: var(--color-text-primary)
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6
|
h6
|
||||||
+margin(4, top)
|
+margin(3, bottom)
|
||||||
|
+padding(3, top)
|
||||||
|
|
||||||
img
|
img
|
||||||
+border-radius(lg)
|
+border-radius(lg)
|
||||||
@ -19,9 +20,4 @@
|
|||||||
|
|
||||||
& >
|
& >
|
||||||
h1:first-of-type,
|
h1:first-of-type,
|
||||||
h2:first-of-type,
|
+padding(0, top)
|
||||||
h3:first-of-type,
|
|
||||||
h4:first-of-type,
|
|
||||||
h5:first-of-type,
|
|
||||||
h6:first-of-type
|
|
||||||
+margin(0, top)
|
|
||||||
|
17
common/static/common/styles/_navigation_global.sass
Normal file
17
common/static/common/styles/_navigation_global.sass
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
.nav-global
|
||||||
|
--nav-global-border-radius: var(--border-radius)
|
||||||
|
--nav-global-border-radius-lg: var(--border-radius-lg)
|
||||||
|
--nav-global-button-height: calc(var(--spacer) * 2.5)
|
||||||
|
--nav-global-font-size: var(--fs-sm)
|
||||||
|
--nav-global-link-padding-y: var(--nav-global-spacer-xs);
|
||||||
|
--nav-global-navbar-height: var(--navbar-primary-height, var(--spacer-6));
|
||||||
|
--nav-global-spacer: var(--spacer)
|
||||||
|
--nav-global-spacer-sm: var(--spacer-2)
|
||||||
|
--nav-global-spacer-xs: var(--spacer-1)
|
||||||
|
|
||||||
|
.btn-primary
|
||||||
|
color: var(--color-accent) !important
|
||||||
|
|
||||||
|
input,
|
||||||
|
.form-control
|
||||||
|
height: var(--nav-global-button-height)
|
@ -1,22 +1,23 @@
|
|||||||
.background-color
|
.background-color
|
||||||
background-color: var(--background-color)
|
background-color: var(--color-bg)
|
||||||
|
|
||||||
.background-color-primary
|
.background-color-primary
|
||||||
background-color: var(--background-color-primary)
|
background-color: var(--color-bg-primary)
|
||||||
|
|
||||||
.background-color-secondary
|
.background-color-secondary
|
||||||
background-color: var(--background-color-secondary)
|
background-color: var(--color-bg-secondary)
|
||||||
|
|
||||||
.background-color-tertiary
|
.background-color-tertiary
|
||||||
background-color: var(--background-color-tertiary)
|
background-color: var(--color-bg-tertiary)
|
||||||
|
|
||||||
.border-bottom-tertiary
|
.border-bottom-tertiary
|
||||||
border-bottom: thin solid var(--background-color-tertiary)
|
border-bottom: thin solid var(--color-bg-tertiary)
|
||||||
|
|
||||||
.cursor-move
|
.cursor-move
|
||||||
&:hover
|
&:hover
|
||||||
cursor: move !important
|
cursor: move !important
|
||||||
|
|
||||||
|
// TODO: move utilities 'fade' and 'show' to web-assets
|
||||||
.fade
|
.fade
|
||||||
opacity: 0
|
opacity: 0
|
||||||
// TODO: make variable 'transition-speed-slow' work
|
// TODO: make variable 'transition-speed-slow' work
|
||||||
@ -36,6 +37,13 @@
|
|||||||
.show
|
.show
|
||||||
opacity: 1
|
opacity: 1
|
||||||
|
|
||||||
|
.text-accent
|
||||||
|
color: var(--color-accent)
|
||||||
|
|
||||||
|
a.text-accent
|
||||||
|
&:hover
|
||||||
|
color: var(--color-accent)
|
||||||
|
|
||||||
.text-underline
|
.text-underline
|
||||||
text-decoration: underline !important
|
text-decoration: underline !important
|
||||||
|
|
||||||
|
@ -2,41 +2,13 @@
|
|||||||
$font-path: '/static/fonts'
|
$font-path: '/static/fonts'
|
||||||
|
|
||||||
/* Import variables.*/
|
/* Import variables.*/
|
||||||
$grid-breakpoints: (xs: 0,sm: 768px,md: 1020px,lg: 1220px,xl: 1380px,xxl: 1680px) !default
|
$grid-breakpoints: (xs: 0,sm: 768px,md: 1020px,lg: 1220px,xl: 1380px,xxl: 1680px)
|
||||||
|
|
||||||
$container-max-widths: (sm: 760px, md: 1020px, lg: 1070px, xl: 1320px, xxl: 1600px)
|
$container-max-widths: (sm: 760px, md: 1020px, lg: 1070px, xl: 1320px, xxl: 1600px)
|
||||||
$container-width: map-get($container-max-widths, 'xl')
|
$container-width: map-get($container-max-widths, 'xl')
|
||||||
|
|
||||||
@import '../../../../assets_shared/src/styles/_media_queries.sass'
|
/* Web Assets. */
|
||||||
@import '../../../../assets_shared/src/styles/_mixins.sass'
|
@import '../../../../assets_shared/src/styles/main.sass'
|
||||||
@import '../../../../assets_shared/src/styles/_variables.sass'
|
|
||||||
|
|
||||||
/* Import Bootstrap. */
|
|
||||||
@import '../../../../assets_shared/src/styles/bootstrap/bootstrap.scss'
|
|
||||||
|
|
||||||
@import '../../../../assets_shared/src/styles/_utilities.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_fonts.sass'
|
|
||||||
|
|
||||||
@import '../../../../assets_shared/src/styles/_bootstrap_overrides.sass'
|
|
||||||
|
|
||||||
@import '../../../../assets_shared/src/styles/_alert.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_badge.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_base.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_box.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_button.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_cards.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_code.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_details.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_footer.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_forms.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_hero.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_list.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_navigation.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_navigation_global.scss'
|
|
||||||
@import '../../../../assets_shared/src/styles/_pagination.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_sidebar.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_table.sass'
|
|
||||||
@import '../../../../assets_shared/src/styles/_type.sass'
|
|
||||||
|
|
||||||
/* Extension Platform specific styling. */
|
/* Extension Platform specific styling. */
|
||||||
@import '_mixins.sass'
|
@import '_mixins.sass'
|
||||||
@ -46,6 +18,7 @@ $container-width: map-get($container-max-widths, 'xl')
|
|||||||
@import '_alert.sass'
|
@import '_alert.sass'
|
||||||
@import '_badge.sass'
|
@import '_badge.sass'
|
||||||
@import '_box.sass'
|
@import '_box.sass'
|
||||||
|
@import '_cards.sass'
|
||||||
@import '_code.sass'
|
@import '_code.sass'
|
||||||
@import '_comments.sass'
|
@import '_comments.sass'
|
||||||
@import '_extension.sass'
|
@import '_extension.sass'
|
||||||
@ -54,6 +27,7 @@ $container-width: map-get($container-max-widths, 'xl')
|
|||||||
@import '_galleria.sass'
|
@import '_galleria.sass'
|
||||||
@import '_hero.sass'
|
@import '_hero.sass'
|
||||||
@import '_list.sass'
|
@import '_list.sass'
|
||||||
|
@import '_navigation_global.sass'
|
||||||
@import '_table.sass'
|
@import '_table.sass'
|
||||||
@import 'ratings/static/ratings/styles/_review.sass'
|
@import 'ratings/static/ratings/styles/_review.sass'
|
||||||
@import 'ratings/static/ratings/styles/_stars.sass'
|
@import 'ratings/static/ratings/styles/_stars.sass'
|
||||||
@ -66,7 +40,7 @@ $container-width: map-get($container-max-widths, 'xl')
|
|||||||
+media-xs
|
+media-xs
|
||||||
width: 60px
|
width: 60px
|
||||||
|
|
||||||
/* Temporarily here until it can be moved to web-assets v2. */
|
/* TODO: temporarily here until it can be moved to web-assets v2. */
|
||||||
.nav-global-links-right
|
.nav-global-links-right
|
||||||
gap: 0 var(--spacer-2)
|
gap: 0 var(--spacer-2)
|
||||||
.navbar-search
|
.navbar-search
|
||||||
@ -77,11 +51,11 @@ $container-width: map-get($container-max-widths, 'xl')
|
|||||||
|
|
||||||
.profile-avatar
|
.profile-avatar
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
|
height: var(--spacer-4)
|
||||||
pointer-events: none
|
pointer-events: none
|
||||||
width: 26px
|
|
||||||
|
|
||||||
.search-highlight
|
.search-highlight
|
||||||
background-color: var(--btn-bg-color)
|
background-color: var(--btn-color-bg)
|
||||||
border-radius: var(--border-radius)
|
border-radius: var(--border-radius)
|
||||||
color: var(--btn-color)
|
color: var(--btn-color)
|
||||||
font-style: normal
|
font-style: normal
|
||||||
@ -97,13 +71,13 @@ $container-width: map-get($container-max-widths, 'xl')
|
|||||||
border-radius: var(--border-radius)
|
border-radius: var(--border-radius)
|
||||||
color: hsl(0, 100%, 90%) !important
|
color: hsl(0, 100%, 90%) !important
|
||||||
display: flex
|
display: flex
|
||||||
+font-weight-bold
|
+fw-bold
|
||||||
font-size: var(--font-size-extra-small)
|
font-size: var(--fs-xs)
|
||||||
justify-content: center
|
justify-content: center
|
||||||
padding-block: .1rem
|
padding-block: .1rem
|
||||||
padding-inline: .4rem
|
padding-inline: var(--spacer-1)
|
||||||
position: absolute
|
position: absolute
|
||||||
top: -.4rem
|
top: calc(var(--spacer-2) * -1)
|
||||||
transition: background-color var(--transition-speed), box-shadow 500ms, color var(--transition-speed)
|
transition: background-color var(--transition-speed), box-shadow 500ms, color var(--transition-speed)
|
||||||
right: -.5rem
|
right: -.5rem
|
||||||
|
|
||||||
|
@ -40,12 +40,12 @@
|
|||||||
.tagger > ul > li:not(.tagger-new) a:visited,
|
.tagger > ul > li:not(.tagger-new) a:visited,
|
||||||
.tagger-new ul a,
|
.tagger-new ul a,
|
||||||
.tagger-new ul a:visited {
|
.tagger-new ul a:visited {
|
||||||
color: var(--text-color);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
.tagger > ul > li:not(.tagger-new) > a,
|
.tagger > ul > li:not(.tagger-new) > a,
|
||||||
.tagger li:not(.tagger-new) > span,
|
.tagger li:not(.tagger-new) > span,
|
||||||
.tagger .tagger-new ul {
|
.tagger .tagger-new ul {
|
||||||
background: var(--btn-bg-color);
|
background: var(--btn-color-bg);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
padding: 4px 4px 4px 8px;
|
padding: 4px 4px 4px 8px;
|
||||||
|
|
||||||
|
@ -125,8 +125,8 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% block nav-upload %}
|
{% block nav-upload %}
|
||||||
<li>
|
<li class="me-2">
|
||||||
<a href="{% url 'extensions:submit' %}" class="btn btn-primary text-primary">
|
<a href="{% url 'extensions:submit' %}" class="btn btn-primary">
|
||||||
<i class="i-upload"></i>
|
<i class="i-upload"></i>
|
||||||
<span>Upload Extension</span>
|
<span>Upload Extension</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
{# TODO: check if template is used and needed #}
|
||||||
<li class="nav-item {% include "common/components/_nav_item_active" %}">
|
<li class="nav-item {% include "common/components/_nav_item_active" %}">
|
||||||
{% include "common/components/nav_link.html" %}
|
{% include "common/components/nav_link.html" %}
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% if name %}
|
{% if name %}
|
||||||
<a class="nav-link {% include "common/components/_nav_item_active" %} {% if classes %}{{ classes }}{% endif %}" href="{% url name %}">{{ title }}</a>
|
<a class="nav-pills-item {% include "common/components/_nav_item_active" %} {% if classes %}{{ classes }}{% endif %}" href="{% url name %}">{{ title }}</a>
|
||||||
{% elif path %}
|
{% elif path %}
|
||||||
<a class="nav-link {% include "common/components/_nav_item_active" %} {% if classes %}{{ classes }}{% endif %}" href="{{ path }}">{{ title }}</a>
|
<a class="nav-pills-item {% include "common/components/_nav_item_active" %} {% if classes %}{{ classes }}{% endif %}" href="{{ path }}">{{ title }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
{% endblock hero %}
|
{% endblock hero %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="box p-5 my-3 is-flatpage">
|
<div class="box my-3 is-flatpage">
|
||||||
{{ flatpage.content|markdown }}
|
{{ flatpage.content|markdown }}
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
@ -10,6 +10,7 @@ class Verb:
|
|||||||
REPORTED_RATING = 'reported rating'
|
REPORTED_RATING = 'reported rating'
|
||||||
REQUESTED_CHANGES = 'requested changes'
|
REQUESTED_CHANGES = 'requested changes'
|
||||||
REQUESTED_REVIEW = 'requested review'
|
REQUESTED_REVIEW = 'requested review'
|
||||||
|
UPLOADED_NEW_VERSION = 'uploaded new version'
|
||||||
|
|
||||||
|
|
||||||
class Flag:
|
class Flag:
|
||||||
|
@ -8,6 +8,7 @@ from django.db.models.signals import m2m_changed, pre_save, post_save, pre_delet
|
|||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
|
||||||
from constants.activity import Flag
|
from constants.activity import Flag
|
||||||
|
from reviewers.models import ApprovalActivity
|
||||||
import extensions.models
|
import extensions.models
|
||||||
import files.models
|
import files.models
|
||||||
|
|
||||||
@ -165,3 +166,26 @@ def _auto_approve_subsequent_uploads(
|
|||||||
args = {'f_id': file.pk, 'pk': instance.pk, 'sender': sender, 's': file.source.name}
|
args = {'f_id': file.pk, 'pk': instance.pk, 'sender': sender, 's': file.source.name}
|
||||||
logger.info('Auto-approving file pk=%(f_id)s of %(sender)s pk=%(pk)s source=%(s)s', args)
|
logger.info('Auto-approving file pk=%(f_id)s of %(sender)s pk=%(pk)s source=%(s)s', args)
|
||||||
file.save(update_fields={'status', 'date_modified'})
|
file.save(update_fields={'status', 'date_modified'})
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=extensions.models.Version)
|
||||||
|
def _create_approval_activity_for_new_version_if_listed(
|
||||||
|
sender: object,
|
||||||
|
instance: extensions.models.Version,
|
||||||
|
created: bool,
|
||||||
|
raw: bool,
|
||||||
|
**kwargs: object,
|
||||||
|
):
|
||||||
|
if raw:
|
||||||
|
return
|
||||||
|
if not created:
|
||||||
|
return
|
||||||
|
extension = instance.extension
|
||||||
|
if not extension.is_listed or not instance.file:
|
||||||
|
return
|
||||||
|
ApprovalActivity(
|
||||||
|
type=ApprovalActivity.ActivityType.UPLOADED_NEW_VERSION,
|
||||||
|
user=instance.file.user,
|
||||||
|
extension=instance.extension,
|
||||||
|
message=f'uploaded new version: {instance.version}',
|
||||||
|
).save()
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// TODO: improve and refactor variable namings
|
// TODO: improve and refactor variable namings
|
||||||
|
|
||||||
const formsetContainer = document.getElementById('add-image-container');
|
const formsetContainer = document.getElementById('add-img-container');
|
||||||
const form = document.getElementById('update-extension-form');
|
const form = document.getElementById('update-extension-form');
|
||||||
const btnAddImage = document.getElementById('btn-add-image');
|
const btnAddImage = document.getElementById('btn-add-img');
|
||||||
const formsetPrefix = 'form';
|
const formsetPrefix = 'form';
|
||||||
const inputTotalForms = document.getElementById(`id_${formsetPrefix}-TOTAL_FORMS`);
|
const inputTotalForms = document.getElementById(`id_${formsetPrefix}-TOTAL_FORMS`);
|
||||||
const tagInput = document.getElementById('id_tags');
|
const tagInput = document.getElementById('id_tags');
|
||||||
@ -28,7 +28,7 @@ function appendImageUploadForm() {
|
|||||||
const formRow = document.createElement('div');
|
const formRow = document.createElement('div');
|
||||||
const newFormHTML = `
|
const newFormHTML = `
|
||||||
<div class="previews-list-item">
|
<div class="previews-list-item">
|
||||||
<div class="align-items-center d-flex previews-list-item-thumbnail pl-3">
|
<div class="align-items-center d-flex previews-list-item-thumbnail ps-3">
|
||||||
<div class="js-input-img-thumbnail previews-list-item-thumbnail-img" title="Preview">
|
<div class="js-input-img-thumbnail previews-list-item-thumbnail-img" title="Preview">
|
||||||
<div class="align-items-center d-flex js-input-img-thumbnail-icon justify-content-center">
|
<div class="align-items-center d-flex js-input-img-thumbnail-icon justify-content-center">
|
||||||
<i class="i-image"></i>
|
<i class="i-image"></i>
|
||||||
@ -44,10 +44,10 @@ function appendImageUploadForm() {
|
|||||||
<input accept="image/jpg,image/jpeg,image/png,image/webp,video/mp4" class="form-control js-input-img" id="id_${formsetPrefix}-${i}-source" type="file" name="${formsetPrefix}-${i}-source">
|
<input accept="image/jpg,image/jpeg,image/png,image/webp,video/mp4" class="form-control js-input-img" id="id_${formsetPrefix}-${i}-source" type="file" name="${formsetPrefix}-${i}-source">
|
||||||
<ul class="pt-0">
|
<ul class="pt-0">
|
||||||
<li>
|
<li>
|
||||||
<button class="btn btn-link btn-sm js-btn-reset-img-upload-form pl-2 pr-0"><i class="i-refresh"></i> Reset</button>
|
<button class="btn btn-link btn-sm js-btn-reset-img-upload-form ps-2 pe-0"><i class="i-refresh"></i> Reset</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button class="btn btn-link btn-sm js-btn-remove-img-upload-form pl-2 pr-0"><i class="i-trash"></i> Delete</button>
|
<button class="btn btn-link btn-sm js-btn-remove-img-upload-form ps-2 pe-0"><i class="i-trash"></i> Delete</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
{% trans "Version History" %}
|
{% trans "Version History" %}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<span class="ml-auto"></span>
|
<span class="ms-auto"></span>
|
||||||
|
|
||||||
<div class="btn-row">
|
<div class="btn-row">
|
||||||
{% if is_maintainer %}
|
{% if is_maintainer %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<a href="{% url "extensions:by-support" support_slug=slug %}" title="Support: {{ name }}"
|
<a href="{% url "extensions:by-support" support_slug=slug %}" title="Support: {{ name }}"
|
||||||
class="badge text-decoration-none align-middle {% if not small %}px-3 py-2 my-1{% endif %} badge-dark{#% if slug == 'official' %}primary{% elif slug == 'community' %}success{% else %}warning{% endif % #}"
|
class="badge text-decoration-none align-middle {% if not small %}px-3 py-2 my-1{% endif %} badge-dark{#% if slug == 'official' %}primary{% elif slug == 'community' %}success{% else %}warning{% endif % #}"
|
||||||
style="{% if not small %}font-size: var(--font-size-base);{% endif %}">
|
style="{% if not small %}font-size: var(--fs-base);{% endif %}">
|
||||||
<b>{{ name }}</b>
|
<b>{{ name }}</b>
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,68 +1,69 @@
|
|||||||
{% load common filters %}
|
{% load common filters %}
|
||||||
{% with latest=extension.latest_version thumbnail_360p_url=extension.get_previews.0.thumbnail_360p_url %}
|
{% with latest=extension.latest_version thumbnail_360p_url=extension.previews.listed.first.thumbnail_360p_url %}
|
||||||
|
<div class="cards-item">
|
||||||
|
<div class="cards-item-content">
|
||||||
|
<a href="{{ extension.get_absolute_url }}">
|
||||||
|
<div class="cards-item-thumbnail">
|
||||||
|
<img alt="{{ extension.name }}" src="{{ thumbnail_360p_url }}" title="{{ extension.name }}">
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<h3 class="cards-item-title">
|
||||||
|
<a href="{{ extension.get_absolute_url }}">{{ extension.name }}</a>
|
||||||
|
</h3>
|
||||||
|
<div class="cards-item-excerpt">
|
||||||
|
<p>
|
||||||
|
{{ latest.tagline }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="cards-item-extra">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
{% if extension.team %}
|
||||||
|
{% with team=extension.team %}
|
||||||
|
<a href="{{ team.get_absolute_url }}" title="{{ team.name }}">{{ team.name }}</a>
|
||||||
|
{% endwith %}
|
||||||
|
{% elif extension.authors.count %}
|
||||||
|
{% include "extensions/components/authors.html" %}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div class="ext-card {% if blur %}is-background-blur{% endif %}">
|
<ul class="cards-item-extra-rating-stars">
|
||||||
{% if blur %}
|
{% if extension.average_score %}
|
||||||
<div class="ext-card-thumbnail-blur" style="background-image: url({{ thumbnail_360p_url }});"></div>
|
<li>
|
||||||
{% endif %}
|
<a class="align-items-center d-flex" href="{{ extension.get_ratings_url }}">
|
||||||
|
{% include "ratings/components/average.html" with score=extension.average_score %}
|
||||||
|
({{ extension.text_ratings_count|int_compact }})
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<a class="ext-card-thumbnail" href="{{ extension.get_absolute_url }}">
|
{% if extension.download_count %}
|
||||||
<div class="ext-card-thumbnail-img" style="background-image: url({{ thumbnail_360p_url }});" title="{{ extension.name }}"></div>
|
<li title="{{ extension.download_count }} downloads">
|
||||||
</a>
|
<i class="i-download"></i> {{ extension.download_count | int_compact }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="ext-card-body">
|
{% if show_type %}
|
||||||
<h3 class="ext-card-title">
|
<li class="ms-auto">
|
||||||
<a href="{{ extension.get_absolute_url }}">{{ extension.name }}</a>
|
{{ extension.get_type_display }}
|
||||||
</h3>
|
</li>
|
||||||
<p>
|
{% endif %}
|
||||||
{{ latest.tagline }}
|
</ul>
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul class="ext-list-details">
|
{% if latest.tags.count %}
|
||||||
<li class="ext-card-author">
|
<ul>
|
||||||
{% if extension.team %}
|
{% for tag in latest.tags.all %}
|
||||||
{% with team=extension.team %}
|
<li>
|
||||||
<a href="{{ team.get_absolute_url }}" title="{{ team.name }}">{{ team.name }}</a>
|
{% include "extensions/components/badge_tag.html" with small=True version=latest %}
|
||||||
{% endwith %}
|
</li>
|
||||||
{% elif extension.authors.count %}
|
{% endfor %}
|
||||||
{% include "extensions/components/authors.html" %}
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul class="ext-list-details mt-1">
|
</div>
|
||||||
{% if extension.average_score %}
|
{# Author/admin tools can be added here in an extending template #}
|
||||||
<li>
|
{% block admin %}{% endblock admin %}
|
||||||
<a href="{{ extension.get_ratings_url }}">
|
</div>
|
||||||
{% include "ratings/components/average.html" with score=extension.average_score %}
|
|
||||||
({{ extension.text_ratings_count|int_compact }})
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if extension.download_count %}
|
|
||||||
<li title="{{ extension.download_count }} downloads">
|
|
||||||
<i class="i-download"></i> {{ extension.download_count | int_compact }}
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if show_type %}
|
|
||||||
<li class="ml-auto">
|
|
||||||
{{ extension.get_type_display }}
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{% if latest.tags.count %}
|
|
||||||
<ul class="ext-list-details ext-card-tags">
|
|
||||||
<li class="ext-card-tags">
|
|
||||||
{% include "extensions/components/tags.html" with small=True version=latest %}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Author/admin tools can be added here in an extending template #}
|
|
||||||
{% block admin %}{% endblock admin %}
|
|
||||||
</div>
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
{# Info Summary #}
|
{# Info Summary #}
|
||||||
<section class="ext-detail-info">
|
<section class="ext-detail-info">
|
||||||
<div class="card">
|
<div class="card p-0">
|
||||||
{% if is_initial %}
|
{% if is_initial %}
|
||||||
<div class="badge badge-info card-badge">
|
<div class="badge badge-card badge-info">
|
||||||
Information retrieved from manifest
|
Information retrieved from manifest
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -19,11 +19,13 @@
|
|||||||
|
|
||||||
{# Description #}
|
{# Description #}
|
||||||
{% block extension_description %}
|
{% block extension_description %}
|
||||||
<section id="about" class="mt-3">
|
{% if extension.description %}
|
||||||
<div class="box ext-detail-description">
|
<section id="about" class="mt-3">
|
||||||
{{ extension.description|markdown }}
|
<div class="box ext-detail-description">
|
||||||
</div>
|
{{ extension.description|markdown }}
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
{% endblock extension_description %}
|
{% endblock extension_description %}
|
||||||
|
|
||||||
{# What's New #}
|
{# What's New #}
|
||||||
@ -82,7 +84,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="mb-0"><i class="i-check mr-0"></i> This extension does not require special permissions.</p>
|
<p class="mb-0"><i class="i-check me-0"></i> This extension does not require special permissions.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -125,7 +127,7 @@
|
|||||||
<dt>{% trans 'Rating' %}</dt>
|
<dt>{% trans 'Rating' %}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{% if extension.average_score %}
|
{% if extension.average_score %}
|
||||||
<a href="{{ extension.get_ratings_url }}" class="text-decoration-none">
|
<a href="{{ extension.get_ratings_url }}" class="align-items-center d-flex stars-helper-detail text-decoration-none">
|
||||||
{% include "ratings/components/average.html" with score=extension.average_score %}
|
{% include "ratings/components/average.html" with score=extension.average_score %}
|
||||||
({{ extension.ratings.listed.count }})
|
({{ extension.ratings.listed.count }})
|
||||||
</a>
|
</a>
|
||||||
@ -274,7 +276,7 @@
|
|||||||
{% trans 'Reviews' %}
|
{% trans 'Reviews' %}
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
<a href="{{ extension.get_ratings_url }}" class="ml-auto">See all</a>
|
<a href="{{ extension.get_ratings_url }}" class="ms-auto">See all</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
<section class="card p-3 mt-3">
|
<section class="card p-3 mt-3">
|
||||||
<div class="btn-col">
|
<div class="btn-col">
|
||||||
<button type="submit" name="save_draft" class="btn btn-primary btn-warning">
|
<button type="submit" name="save_draft" class="btn btn-warning">
|
||||||
<i class="i-check"></i>
|
<i class="i-check"></i>
|
||||||
<span>{% trans 'Save Draft' %}</span>
|
<span>{% trans 'Save Draft' %}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="hero-background" style="background-image: url(https://www.blender.org/wp-content/uploads/2022/08/piotr-krynski-scanislands-blender-33lts-crop.jpg); background-position-y: 50%"></div>
|
<div class="hero-bg" style="background-image: url(https://www.blender.org/wp-content/uploads/2022/08/piotr-krynski-scanislands-blender-33lts-crop.jpg); background-position-y: 50%"></div>
|
||||||
<div class="hero-overlay"></div>
|
<div class="hero-overlay"></div>
|
||||||
<div class="hero-credits"></div>
|
<div class="hero-credits"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -38,10 +38,10 @@
|
|||||||
<h2>
|
<h2>
|
||||||
<a href="{% url 'extensions:by-type' type_slug='add-ons' %}">Add-ons</a>
|
<a href="{% url 'extensions:by-type' type_slug='add-ons' %}">Add-ons</a>
|
||||||
</h2>
|
</h2>
|
||||||
<a href="{% url 'extensions:by-type' type_slug='add-ons' %}" class="ml-auto">See all</a>
|
<a href="{% url 'extensions:by-type' type_slug='add-ons' %}" class="ms-auto">See all</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Extend Blender capabilities with these add-ons by the community.</p>
|
<p>Extend Blender capabilities with these add-ons by the community.</p>
|
||||||
<div class="cards-list mt-3">
|
<div class="cards cards-lg-4 cards-md-3 cards-sm-2 mt-3">
|
||||||
{% for extension in addons %}
|
{% for extension in addons %}
|
||||||
{% include "extensions/components/card.html" %}
|
{% include "extensions/components/card.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -53,12 +53,12 @@
|
|||||||
<h2>
|
<h2>
|
||||||
<a href="{% url 'extensions:by-type' type_slug='themes' %}">Themes</a>
|
<a href="{% url 'extensions:by-type' type_slug='themes' %}">Themes</a>
|
||||||
</h2>
|
</h2>
|
||||||
<a href="{% url 'extensions:by-type' type_slug='themes' %}" class="ml-auto fw-normal">
|
<a href="{% url 'extensions:by-type' type_slug='themes' %}" class="ms-auto fw-normal">
|
||||||
See all
|
See all
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p>Blender themes to your liking. Dark, light, flat, colorful, and everything in between.</p>
|
<p>Blender themes to your liking. Dark, light, flat, colorful, and everything in between.</p>
|
||||||
<div class="cards-list mt-3">
|
<div class="cards cards-lg-4 cards-md-3 cards-sm-2 mt-3">
|
||||||
{% for extension in themes %}
|
{% for extension in themes %}
|
||||||
{% include "extensions/components/card.html" %}
|
{% include "extensions/components/card.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
<div class="my-5 text-center">
|
<div class="my-5 text-center">
|
||||||
Got an add-on or theme to share with the community?
|
Got an add-on or theme to share with the community?
|
||||||
<a href="{% url 'extensions:submit' %}" class="text-primary ml-2">
|
<a href="{% url 'extensions:submit' %}" class="text-accent ms-2">
|
||||||
Upload
|
Upload
|
||||||
<i class="i-chevron-right"></i>
|
<i class="i-chevron-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if tag %}
|
{% if tag %}
|
||||||
<h2 class="d-flex align-items-center">
|
<h2 class="d-flex align-items-center">
|
||||||
<span class="mr-3">{% blocktranslate %}Extensions with the tag{% endblocktranslate %}</span>
|
<span class="me-3">{% blocktranslate %}Extensions with the tag{% endblocktranslate %}</span>
|
||||||
{% include "extensions/components/badge_tag.html" %}
|
{% include "extensions/components/badge_tag.html" %}
|
||||||
</h2>
|
</h2>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -47,7 +47,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{% if object_list %}
|
{% if object_list %}
|
||||||
<div class="cards-list card-layout-horizontal cards-3">
|
<div class="cards cards-3">
|
||||||
{% for extension in object_list %}
|
{% for extension in object_list %}
|
||||||
{% include "extensions/components/card.html" with show_type=False %}
|
{% include "extensions/components/card.html" with show_type=False %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -1,44 +1,42 @@
|
|||||||
{% load common %}
|
{% load common %}
|
||||||
{# Upload new preview images #}
|
{# Upload new preview images #}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="previews-upload">
|
<div id="add-img-container" class="previews-list">
|
||||||
<div id="add-image-container" class="previews-list">
|
{{ add_preview_formset.management_form }}
|
||||||
{{ add_preview_formset.management_form }}
|
{{ add_preview_formset.non_form_errors }}
|
||||||
{{ add_preview_formset.non_form_errors }}
|
{% for newform in add_preview_formset %}
|
||||||
{% for newform in add_preview_formset %}
|
{% with inlineform=newform|add_form_classes %}
|
||||||
{% with inlineform=newform|add_form_classes %}
|
<div class="ext-edit-field-row js-ext-edit-field-row">
|
||||||
<div class="ext-edit-field-row js-ext-edit-field-row">
|
<div class="previews-list-item">
|
||||||
<div class="previews-list-item">
|
<div class="d-flex previews-list-item-thumbnail ps-3">
|
||||||
<div class="align-items-center d-flex previews-list-item-thumbnail pl-3">
|
<div class="js-input-img-thumbnail previews-list-item-thumbnail-img" title="Preview">
|
||||||
<div class="js-input-img-thumbnail previews-list-item-thumbnail-img" title="Preview">
|
<div class="align-items-center d-flex js-input-img-thumbnail-icon justify-content-center">
|
||||||
<div class="align-items-center d-flex js-input-img-thumbnail-icon justify-content-center">
|
<i class="i-image"></i>
|
||||||
<i class="i-image"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="details flex-grow-1">
|
|
||||||
<div class="js-input-img-caption-helper mb-2">
|
|
||||||
{% include "common/components/field.html" with field=inlineform.caption label='Caption' %}
|
|
||||||
</div>
|
|
||||||
<div class="align-items-center d-flex js-input-img-helper justify-content-between">
|
|
||||||
{% include "common/components/field.html" with field=inlineform.source label='File' %}
|
|
||||||
<ul class="pt-0">
|
|
||||||
<li>
|
|
||||||
<button class="btn btn-link btn-sm js-btn-reset-img-upload-form pl-2 pr-0"><i class="i-refresh"></i> Reset</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="details flex-grow-1">
|
||||||
|
<div class="js-input-img-caption-helper mb-2">
|
||||||
|
{% include "common/components/field.html" with field=inlineform.caption label='Caption' %}
|
||||||
|
</div>
|
||||||
|
<div class="align-items-center d-flex js-input-img-helper justify-content-between">
|
||||||
|
{% include "common/components/field.html" with field=inlineform.source label='File' %}
|
||||||
|
<ul class="pt-0">
|
||||||
|
<li>
|
||||||
|
<button class="btn btn-link btn-sm js-btn-reset-img-upload-form ps-2 pe-0"><i class="i-refresh"></i> Reset</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ inlineform.non_form_errors }}
|
</div>
|
||||||
{% endwith %}
|
{{ inlineform.non_form_errors }}
|
||||||
{% endfor %}
|
{% endwith %}
|
||||||
</div>
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-right mt-3">
|
<div class="col text-right mt-3">
|
||||||
<a id="btn-add-image" class="btn">
|
<a id="btn-add-img" class="btn">
|
||||||
<i class="i-plus"></i>
|
<i class="i-plus"></i>
|
||||||
<span>{% trans 'Add Preview' %}</span>
|
<span>{% trans 'Add Preview' %}</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -2,16 +2,17 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block admin %}
|
{% block admin %}
|
||||||
<div class="ext-card-admin p-3">
|
<div class="bg-secondary cards-item-extra pt-3">
|
||||||
<div>
|
<ul class="w-100">
|
||||||
<a href="{{ extension.get_manage_url }}" class="btn btn-sm">
|
<li class="d-flex justify-content-between me-0 w-100">
|
||||||
<i class="i-edit"></i>
|
<a href="{{ extension.get_manage_url }}" class="btn btn-sm">
|
||||||
<span>{% trans 'Edit' %}</span>
|
<i class="i-edit"></i>
|
||||||
</a>
|
<span>{% trans 'Edit' %}</span>
|
||||||
</div>
|
</a>
|
||||||
|
<div class="align-items-center d-flex">
|
||||||
<div>
|
{% include "common/components/status.html" with object=extension class="badge-tag" %}
|
||||||
{% include "common/components/status.html" with object=extension %}
|
</div>
|
||||||
</div>
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endblock admin %}
|
{% endblock admin %}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
{% if object_list %}
|
{% if object_list %}
|
||||||
<div class="cards-list">
|
<div class="cards">
|
||||||
{% for extension in object_list %}
|
{% for extension in object_list %}
|
||||||
{% include "extensions/manage/components/card.html" with show_type=True %}
|
{% include "extensions/manage/components/card.html" with show_type=True %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
<small>Source File</small>
|
<small>Source File</small>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="ml-auto">
|
<li class="ms-auto">
|
||||||
{% include "common/components/field.html" with field=inlineform.DELETE %}
|
{% include "common/components/field.html" with field=inlineform.DELETE %}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -153,7 +153,7 @@
|
|||||||
const previewDragContainer = document.querySelector('.js-previews-drag-container');
|
const previewDragContainer = document.querySelector('.js-previews-drag-container');
|
||||||
const previewDragClass = 'js-preview-drag';
|
const previewDragClass = 'js-preview-drag';
|
||||||
|
|
||||||
{% comment %} dragula([document.querySelector('.js-preview-drag'), document.querySelector('.cards-list')]); {% endcomment %}
|
{% comment %} dragula([document.querySelector('.js-preview-drag'), document.querySelector('.cards')]); {% endcomment %}
|
||||||
dragula([previewDragContainer, previewDragContainer], {
|
dragula([previewDragContainer, previewDragContainer], {
|
||||||
moves: function (el, container, handle) {
|
moves: function (el, container, handle) {
|
||||||
return handle.className.includes(previewDragClass);
|
return handle.className.includes(previewDragClass);
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<span class="show-on-collapse blender-version">
|
<span class="show-on-collapse blender-version">
|
||||||
{% include "extensions/components/blender_version.html" with version=version %}
|
{% include "extensions/components/blender_version.html" with version=version %}
|
||||||
</span>
|
</span>
|
||||||
<ul class="ml-auto">
|
<ul class="ms-auto">
|
||||||
<li class="show-on-collapse">{{ version.file.size_bytes|filesizeformat }}</li>
|
<li class="show-on-collapse">{{ version.file.size_bytes|filesizeformat }}</li>
|
||||||
<li class="show-on-collapse"><i class="i-download"></i> {{ version.download_count }}</li>
|
<li class="show-on-collapse"><i class="i-download"></i> {{ version.download_count }}</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -10,6 +10,7 @@ from common.tests.factories.users import UserFactory
|
|||||||
from common.tests.utils import _get_all_form_errors
|
from common.tests.utils import _get_all_form_errors
|
||||||
from extensions.models import Extension, Version
|
from extensions.models import Extension, Version
|
||||||
from files.models import File
|
from files.models import File
|
||||||
|
from reviewers.models import ApprovalActivity
|
||||||
import utils
|
import utils
|
||||||
|
|
||||||
|
|
||||||
@ -425,6 +426,14 @@ class NewVersionTest(TestCase):
|
|||||||
f'/add-ons/{self.extension.slug}/manage/versions/new/{file.pk}/',
|
f'/add-ons/{self.extension.slug}/manage/versions/new/{file.pk}/',
|
||||||
)
|
)
|
||||||
self.assertEqual(self.extension.versions.count(), 1)
|
self.assertEqual(self.extension.versions.count(), 1)
|
||||||
|
self.extension.approve()
|
||||||
|
self.assertEqual(
|
||||||
|
ApprovalActivity.objects.filter(
|
||||||
|
extension=self.extension,
|
||||||
|
type=ApprovalActivity.ActivityType.UPLOADED_NEW_VERSION,
|
||||||
|
).count(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
# Check step 2: finalise new version and send to review
|
# Check step 2: finalise new version and send to review
|
||||||
url = response['Location']
|
url = response['Location']
|
||||||
@ -444,3 +453,10 @@ class NewVersionTest(TestCase):
|
|||||||
self.assertEqual(new_version.schema_version, '1.0.0')
|
self.assertEqual(new_version.schema_version, '1.0.0')
|
||||||
self.assertEqual(new_version.release_notes, 'new version')
|
self.assertEqual(new_version.release_notes, 'new version')
|
||||||
self.assertEqual(new_version.file.get_status_display(), 'Approved')
|
self.assertEqual(new_version.file.get_status_display(), 'Approved')
|
||||||
|
self.assertEqual(
|
||||||
|
ApprovalActivity.objects.filter(
|
||||||
|
extension=self.extension,
|
||||||
|
type=ApprovalActivity.ActivityType.UPLOADED_NEW_VERSION,
|
||||||
|
).count(),
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
@ -18,6 +18,7 @@ VERB2FLAGS = {
|
|||||||
Verb.REPORTED_RATING: [Flag.MODERATOR],
|
Verb.REPORTED_RATING: [Flag.MODERATOR],
|
||||||
Verb.REQUESTED_CHANGES: [Flag.AUTHOR, Flag.REVIEWER],
|
Verb.REQUESTED_CHANGES: [Flag.AUTHOR, Flag.REVIEWER],
|
||||||
Verb.REQUESTED_REVIEW: [Flag.MODERATOR, Flag.REVIEWER],
|
Verb.REQUESTED_REVIEW: [Flag.MODERATOR, Flag.REVIEWER],
|
||||||
|
Verb.UPLOADED_NEW_VERSION: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ def _create_notifications(
|
|||||||
notifications = []
|
notifications = []
|
||||||
|
|
||||||
flags = VERB2FLAGS.get(instance.verb, None)
|
flags = VERB2FLAGS.get(instance.verb, None)
|
||||||
if not flags:
|
if flags is None:
|
||||||
logger.warning(f'no follower flags for verb={instance.verb}, nobody will be notified')
|
logger.warning(f'no follower flags for verb={instance.verb}, nobody will be notified')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ and will most likely fail due to differences in configuration paths and so on.
|
|||||||
To avoid adding more dependencies to the project itself, `ansible` uses its own `virtualenv`.
|
To avoid adding more dependencies to the project itself, `ansible` uses its own `virtualenv`.
|
||||||
To set it up use the following commands:
|
To set it up use the following commands:
|
||||||
|
|
||||||
virtualenv .venv -p python
|
python3.10 -m venv .venv
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
h1 {
|
h1 {
|
||||||
background: linear-gradient(to right, #0cc, violet);
|
background: linear-gradient(to right, #0cc, violet);
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
-webkit-background-clip: text;
|
-webkit-bg-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
font-size: 1.6em;
|
font-size: 1.6em;
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
-webkit-mask-size: var(--star-size) var(--star-size)
|
-webkit-mask-size: var(--star-size) var(--star-size)
|
||||||
mask-size: var(--star-size) var(--star-size)
|
mask-size: var(--star-size) var(--star-size)
|
||||||
text-align: left
|
text-align: left
|
||||||
|
transform: translateY(-.2rem)
|
||||||
width: var(--stars-number)
|
width: var(--stars-number)
|
||||||
|
|
||||||
span
|
span
|
||||||
@ -62,6 +63,11 @@
|
|||||||
--star-size: 1.6em
|
--star-size: 1.6em
|
||||||
width: 8em
|
width: 8em
|
||||||
|
|
||||||
|
// TODO: refactor stars-helper
|
||||||
|
.stars-helper
|
||||||
|
max-height: 1.4rem
|
||||||
|
transform: translateY(-.1rem)
|
||||||
|
|
||||||
.ratings-summary
|
.ratings-summary
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
@ -87,9 +93,9 @@
|
|||||||
text-decoration: none
|
text-decoration: none
|
||||||
|
|
||||||
span
|
span
|
||||||
color: var(--text-color-secondary)
|
color: var(--color-text-secondary)
|
||||||
display: block
|
display: block
|
||||||
font-size: var(--font-size-base)
|
font-size: var(--fs-base)
|
||||||
|
|
||||||
.stars
|
.stars
|
||||||
+margin(auto, x)
|
+margin(auto, x)
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
{% blocktranslate asvar title with score=score %}Rated {{ score }} out of 5{% endblocktranslate %}
|
{% blocktranslate asvar title with score=score %}Rated {{ score }} out of 5{% endblocktranslate %}
|
||||||
|
|
||||||
<span class="stars{% if size %} {{ size }}{% endif %}" title="{{ title }}">
|
<span class="stars me-1 {% if size %} {{ size }}{% endif %}" title="{{ title }}">
|
||||||
<span style="width: {% widthratio score 5 100 %}%"></span>
|
<span style="width: {% widthratio score 5 100 %}%"></span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
{{ rating.user }}
|
{{ rating.user }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="mr-auto">
|
<li class="align-items-center d-flex me-auto">
|
||||||
{% with score_percentage=rating.score %}
|
{% with score_percentage=rating.score %}
|
||||||
<a href="{{ extension.get_ratings_url }}?score={{ rating.score }}">
|
<a class="stars-helper" href="{{ extension.get_ratings_url }}?score={{ rating.score }}">
|
||||||
{% include "ratings/components/average.html" with score=rating.score %}
|
{% include "ratings/components/average.html" with score=rating.score %}
|
||||||
</a>
|
</a>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{% block page_title %}Rate {{ extension.name }}{% endblock page_title %}
|
{% block page_title %}Rate {{ extension.name }}{% endblock page_title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container rating-form">
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% with form=form|add_form_classes %}
|
{% with form=form|add_form_classes %}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
{% if score %}
|
{% if score %}
|
||||||
<div class="ml-auto">
|
<div class="ms-auto">
|
||||||
<a href="{{ extension.get_ratings_url }}" class="text-muted">See all</a>
|
<a href="{{ extension.get_ratings_url }}" class="text-muted">See all</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
18
reviewers/migrations/0009_alter_approvalactivity_type.py
Normal file
18
reviewers/migrations/0009_alter_approvalactivity_type.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.11 on 2024-04-29 17:33
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('reviewers', '0008_alter_approvalactivity_message'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='approvalactivity',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('COM', 'Comment'), ('APR', 'Approved'), ('AWC', 'Awaiting Changes'), ('AWR', 'Awaiting Review'), ('UNV', 'Uploaded New Version')], default='COM', max_length=3),
|
||||||
|
),
|
||||||
|
]
|
@ -80,6 +80,7 @@ class ApprovalActivity(CreatedModifiedMixin, RecordDeletionMixin, models.Model):
|
|||||||
APPROVED = "APR", _("Approved")
|
APPROVED = "APR", _("Approved")
|
||||||
AWAITING_CHANGES = "AWC", _("Awaiting Changes")
|
AWAITING_CHANGES = "AWC", _("Awaiting Changes")
|
||||||
AWAITING_REVIEW = "AWR", _("Awaiting Review")
|
AWAITING_REVIEW = "AWR", _("Awaiting Review")
|
||||||
|
UPLOADED_NEW_VERSION = "UNV", _("Uploaded New Version")
|
||||||
|
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
|
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
|
||||||
extension = models.ForeignKey(
|
extension = models.ForeignKey(
|
||||||
|
@ -30,6 +30,7 @@ def _create_action_from_review_and_follow(
|
|||||||
ApprovalActivity.ActivityType.AWAITING_CHANGES: Verb.REQUESTED_CHANGES,
|
ApprovalActivity.ActivityType.AWAITING_CHANGES: Verb.REQUESTED_CHANGES,
|
||||||
ApprovalActivity.ActivityType.AWAITING_REVIEW: Verb.REQUESTED_REVIEW,
|
ApprovalActivity.ActivityType.AWAITING_REVIEW: Verb.REQUESTED_REVIEW,
|
||||||
ApprovalActivity.ActivityType.COMMENT: Verb.COMMENTED,
|
ApprovalActivity.ActivityType.COMMENT: Verb.COMMENTED,
|
||||||
|
ApprovalActivity.ActivityType.UPLOADED_NEW_VERSION: Verb.UPLOADED_NEW_VERSION,
|
||||||
}
|
}
|
||||||
action.send(
|
action.send(
|
||||||
instance.user,
|
instance.user,
|
||||||
|
@ -6,27 +6,25 @@
|
|||||||
{{ extension.name }}
|
{{ extension.name }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>{% include "extensions/components/authors.html" %}</td>
|
||||||
{% if extension.authors.count %}
|
|
||||||
{% include "extensions/components/authors.html" %}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td title="{{ extension.date_created }}">{{ extension.date_created|naturaltime_compact }}</td>
|
<td title="{{ extension.date_created }}">{{ extension.date_created|naturaltime_compact }}</td>
|
||||||
<td class="d-flex">
|
<td class="d-flex">
|
||||||
<a href="{{ extension.get_review_url }}#activity">
|
<a href="{{ extension.get_review_url }}#activity">
|
||||||
<span>{{ extension.review_activity.all|length }}</span>
|
<span>{{ stats.count }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="{{ extension.get_review_url }}#activity-{{ stats.last_activity.id }}" class="ms-3">
|
||||||
{% if extension.review_activity.all %}
|
<span>{{ stats.last_activity.date_created|naturaltime_compact }}</span>
|
||||||
<a href="{{ extension.get_review_url }}#activity-{{ extension.review_activity.all.last.id }}" class="ml-3">
|
|
||||||
<span>{{ extension.review_activity.all.last.date_created|naturaltime_compact }}</span>
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
|
||||||
{% include "files/components/scan_details_flag.html" with suspicious_files=extension.suspicious_files %}
|
{% include "files/components/scan_details_flag.html" with suspicious_files=extension.suspicious_files %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ extension.get_review_url }}" class="text-decoration-none">
|
<a href="{{ extension.get_review_url }}" class="text-decoration-none">
|
||||||
{% include "common/components/status.html" with object=extension class="d-block" %}
|
{% with last_type=stats.last_type_display|default:"Awaiting Review" %}
|
||||||
|
<div class="d-block badge badge-status-{{ last_type|slugify }}">
|
||||||
|
<i class="i-eye"></i>
|
||||||
|
<span>{{ last_type }}</span>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
{% trans "Version History" %}
|
{% trans "Version History" %}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<span class="ml-auto"></span>
|
<span class="ms-auto"></span>
|
||||||
|
|
||||||
<div class="btn-row">
|
<div class="btn-row">
|
||||||
{% if is_maintainer %}
|
{% if is_maintainer %}
|
||||||
@ -101,8 +101,7 @@
|
|||||||
{% for activity in extension.review_activity.all %}
|
{% for activity in extension.review_activity.all %}
|
||||||
<li id="activity-{{ activity.id }}">
|
<li id="activity-{{ activity.id }}">
|
||||||
|
|
||||||
{# All activities except comments. #}
|
{% if activity.type in status_change_types %}
|
||||||
{% if activity.type != 'COM' %}
|
|
||||||
<div class="activity-item activity-status-change activity-status-{{ activity.get_type_display|slugify }}">
|
<div class="activity-item activity-status-change activity-status-{{ activity.get_type_display|slugify }}">
|
||||||
<i class="activity-icon i-activity-{{ activity.get_type_display|slugify }}"></i>
|
<i class="activity-icon i-activity-{{ activity.get_type_display|slugify }}"></i>
|
||||||
|
|
||||||
@ -139,7 +138,7 @@
|
|||||||
{{ activity.user }}
|
{{ activity.user }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="ml-auto">
|
<li class="ms-auto">
|
||||||
<a href="#activity-{{ activity.id }}" title="{{ activity.date_created }}">
|
<a href="#activity-{{ activity.id }}" title="{{ activity.date_created }}">
|
||||||
{{ activity.date_created|naturaltime_compact }}
|
{{ activity.date_created|naturaltime_compact }}
|
||||||
</a>
|
</a>
|
||||||
@ -167,8 +166,11 @@
|
|||||||
{% include "common/components/field.html" with field=form.message %}
|
{% include "common/components/field.html" with field=form.message %}
|
||||||
|
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<div class="btn-row ml-3 w-100 justify-content-end">
|
<div class="btn-row ms-3 w-100 justify-content-end">
|
||||||
{% include "common/components/field.html" with field=form.type %}
|
{% if is_maintainer or request.user.is_moderator %}
|
||||||
|
{% include "common/components/field.html" with field=form.type %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<button type="submit" id="activity-submit" class="btn btn-primary">
|
<button type="submit" id="activity-submit" class="btn btn-primary">
|
||||||
<span>{% trans "Comment" %}</span>
|
<span>{% trans "Comment" %}</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -34,12 +34,10 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for extension in object_list %}
|
{% for stats in object_list %}
|
||||||
{% if user.is_moderator %}
|
{% with extension=stats.extension %}
|
||||||
{% include 'reviewers/components/review_list_item.html' %}
|
{% include 'reviewers/components/review_list_item.html' with extension=extension stats=stats %}
|
||||||
{% elif extension.status_slug == 'awaiting-review' %}
|
{% endwith %}
|
||||||
{% include 'reviewers/components/review_list_item.html' %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -3,13 +3,21 @@ from django.shortcuts import reverse
|
|||||||
|
|
||||||
from common.tests.factories.extensions import create_version
|
from common.tests.factories.extensions import create_version
|
||||||
from files.models import File
|
from files.models import File
|
||||||
|
from reviewers.models import ApprovalActivity
|
||||||
|
|
||||||
|
|
||||||
class CommentsViewTest(TestCase):
|
class CommentsViewTest(TestCase):
|
||||||
fixtures = ['licenses']
|
fixtures = ['licenses']
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.default_version = create_version(file__status=File.STATUSES.AWAITING_REVIEW)
|
version = create_version(file__status=File.STATUSES.AWAITING_REVIEW)
|
||||||
|
self.default_version = version
|
||||||
|
ApprovalActivity(
|
||||||
|
type=ApprovalActivity.ActivityType.COMMENT,
|
||||||
|
user=version.file.user,
|
||||||
|
extension=version.extension,
|
||||||
|
message='test comment',
|
||||||
|
).save()
|
||||||
|
|
||||||
# List of extensions under review does not require authentication
|
# List of extensions under review does not require authentication
|
||||||
def test_list_visibility(self):
|
def test_list_visibility(self):
|
||||||
|
@ -13,15 +13,51 @@ from reviewers.models import ApprovalActivity
|
|||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
STATUS_CHANGE_TYPES = [
|
||||||
|
ApprovalActivity.ActivityType.APPROVED,
|
||||||
|
ApprovalActivity.ActivityType.AWAITING_CHANGES,
|
||||||
|
ApprovalActivity.ActivityType.AWAITING_REVIEW,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ApprovalQueueView(ListView):
|
class ApprovalQueueView(ListView):
|
||||||
model = Extension
|
model = Extension
|
||||||
paginate_by = 100
|
paginate_by = 100
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Extension.objects.exclude(status=Extension.STATUSES.APPROVED).order_by(
|
qs = (
|
||||||
'-date_created'
|
ApprovalActivity.objects.prefetch_related(
|
||||||
|
'extension',
|
||||||
|
'extension__authors',
|
||||||
|
'extension__versions',
|
||||||
|
'extension__versions__file',
|
||||||
|
'extension__versions__file__validation',
|
||||||
|
)
|
||||||
|
.order_by('-date_created')
|
||||||
|
.all()
|
||||||
)
|
)
|
||||||
|
by_extension = {}
|
||||||
|
result = []
|
||||||
|
for item in qs:
|
||||||
|
extension = item.extension
|
||||||
|
stats = by_extension.get(extension, None)
|
||||||
|
if not stats:
|
||||||
|
# this check guarantees that we add a record only once per extension,
|
||||||
|
# and iterating over qs we get result also ordered by item.date_created
|
||||||
|
stats = {
|
||||||
|
'count': 0,
|
||||||
|
'extension': extension,
|
||||||
|
'last_activity': None,
|
||||||
|
'last_type_display': None,
|
||||||
|
}
|
||||||
|
by_extension[extension] = stats
|
||||||
|
result.append(stats)
|
||||||
|
stats['count'] += 1
|
||||||
|
if not stats.get('last_activity', None):
|
||||||
|
stats['last_activity'] = item
|
||||||
|
if not stats.get('last_type_display', None) and item.type in STATUS_CHANGE_TYPES:
|
||||||
|
stats['last_type_display'] = item.get_type_display
|
||||||
|
return result
|
||||||
|
|
||||||
template_name = 'reviewers/extensions_review_list.html'
|
template_name = 'reviewers/extensions_review_list.html'
|
||||||
|
|
||||||
@ -36,33 +72,31 @@ class ExtensionsApprovalDetailView(DetailView):
|
|||||||
ctx['pending_previews'] = self.object.preview_set.exclude(
|
ctx['pending_previews'] = self.object.preview_set.exclude(
|
||||||
file__status=File.STATUSES.APPROVED
|
file__status=File.STATUSES.APPROVED
|
||||||
)
|
)
|
||||||
|
ctx['status_change_types'] = STATUS_CHANGE_TYPES
|
||||||
|
|
||||||
if self.request.user.is_authenticated:
|
if self.request.user.is_authenticated:
|
||||||
form = ctx['comment_form'] = CommentForm()
|
form = ctx['comment_form'] = CommentForm()
|
||||||
# Remove 'Approved' status from dropdown it not moderator
|
# anyone can comment
|
||||||
filtered_activity_types = ApprovalActivity.ActivityType.choices
|
filtered_activity_types = {ApprovalActivity.ActivityType.COMMENT}
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
if not (user.is_moderator or user.is_superuser):
|
if self.object.has_maintainer(user):
|
||||||
filtered_activity_types = [
|
filtered_activity_types.add(ApprovalActivity.ActivityType.AWAITING_REVIEW)
|
||||||
t
|
if user.is_moderator or user.is_superuser:
|
||||||
for t in ApprovalActivity.ActivityType.choices
|
filtered_activity_types.update(
|
||||||
if t[0]
|
[
|
||||||
not in [
|
|
||||||
ApprovalActivity.ActivityType.APPROVED,
|
ApprovalActivity.ActivityType.APPROVED,
|
||||||
ApprovalActivity.ActivityType.AWAITING_CHANGES,
|
ApprovalActivity.ActivityType.AWAITING_CHANGES,
|
||||||
]
|
]
|
||||||
]
|
)
|
||||||
if not self.object.has_maintainer(user):
|
choices = list(
|
||||||
# Other accounts can only comment
|
filter(
|
||||||
filtered_activity_types = [
|
lambda c: c[0] in filtered_activity_types, ApprovalActivity.ActivityType.choices
|
||||||
t
|
)
|
||||||
for t in ApprovalActivity.ActivityType.choices
|
)
|
||||||
if t[0] == ApprovalActivity.ActivityType.COMMENT
|
form.fields['type'].choices = choices
|
||||||
]
|
form.fields['type'].widget.choices = choices
|
||||||
form.fields['type'].choices = filtered_activity_types
|
if len(choices) == 1:
|
||||||
form.fields['type'].widget.choices = filtered_activity_types
|
form.fields['type'].widget = django.forms.HiddenInput()
|
||||||
if len(filtered_activity_types) == 1:
|
|
||||||
form.fields['type'].widget = django.forms.HiddenInput()
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{% for _slug, badge in badges.items %}
|
{% for _slug, badge in badges.items %}
|
||||||
<img class="mr-2" width="{{ width }}" src="{{ badge.image }}" title="{{ badge.description }}" label="{{ badge.label }}" />
|
<img class="me-2" width="{{ width }}" src="{{ badge.image }}" title="{{ badge.description }}" label="{{ badge.label }}" />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
<img src="{% if user.image %}{{ user.image.url }}{% else %}{% static 'common/images/blank-profile-pic.png' %}{% endif %}" class="profile-avatar {{ classes }}">
|
<img src="{% if user.image %}{{ user.image.url }}{% else %}{% static 'common/images/blank-profile-pic.png' %}{% endif %}" class="profile-avatar {{ classes }}">
|
||||||
{% if show_name %}
|
{% if show_name %}
|
||||||
<span class="ml-2">
|
<span class="ms-2">
|
||||||
{% firstof user.full_name user.username %}
|
{% firstof user.full_name user.username %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="d-none d-md-block col-md-3">
|
<div class="d-none d-md-block col-md-3">
|
||||||
<div class="is-sticky pt-4">
|
<div class="is-sticky pt-4">
|
||||||
<nav class="box nav-drawer-nested">
|
<nav class="box nav-drawer-nested p-3">
|
||||||
<div class="nav-drawer-body fw-bold">
|
<div class="nav-drawer-body fw-bold">
|
||||||
{% include 'users/settings/tabs.html' %}
|
{% include 'users/settings/tabs.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,12 +27,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 mb-4">
|
<div class="col-md-6 mb-4">
|
||||||
<label class="mb-2 h3" for="email">
|
<label class="mb-2 h3" for="email">
|
||||||
<span class="mr-1">Email</span>
|
<span class="me-1">Email</span>
|
||||||
|
|
||||||
{% if user.confirmed_email_at %}
|
{% if user.confirmed_email_at %}
|
||||||
<span class="align-middle badge badge-sm badge-success"><i class="i-check"></i>Confirmed</span>
|
<span class="align-middle badge badge-success fs-xs"><i class="i-check"></i>Confirmed</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="align-middle badge badge-sm badge-warning"><i class="i-alert-triangle"></i>Not yet confirmed</span>
|
<span class="align-middle badge badge-warning fs-xs"><i class="i-alert-triangle"></i>Not yet confirmed</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</label>
|
</label>
|
||||||
<div class="align-items-center d-flex position-relative">
|
<div class="align-items-center d-flex position-relative">
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
{% include "common/components/nav_link.html" with name="users:my-profile" title="Profile" classes="i-home py-2" %}
|
{% include "common/components/nav_link.html" with name="users:my-profile" title="Profile" classes="i-home py-2" %}
|
||||||
|
|
||||||
{% if user.teams.count %}
|
{% if user.teams.count %}
|
||||||
{% include "common/components/nav_link.html" with name="teams:list" title="Teams" classes="i-people py-2" %}
|
{% include "common/components/nav_link.html" with name="teams:list" title="Teams" classes="i-users py-2" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="nav-pills-divider"></div>
|
||||||
|
|
||||||
{% include "common/components/nav_link.html" with name="users:my-profile-delete" title="Delete account" classes="i-trash py-2" %}
|
{% include "common/components/nav_link.html" with name="users:my-profile-delete" title="Delete account" classes="i-trash py-2" %}
|
||||||
</div>
|
</div>
|
||||||
{% endspaceless %}
|
{% endspaceless %}
|
||||||
|
Loading…
Reference in New Issue
Block a user