Skip to content

Commit

Permalink
Merge branch '4.x' of https://github.com/craftcms/cms into 5.x
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/translations/en/app.php
#	src/web/assets/pluginstore/PluginStoreAsset.php
#	src/web/assets/pluginstore/dist/css/app.css
#	src/web/assets/pluginstore/dist/css/app.css.map
#	src/web/assets/pluginstore/dist/js/app.js
#	src/web/assets/pluginstore/dist/js/app.js.map
  • Loading branch information
brandonkelly committed Oct 8, 2024
2 parents e01adb1 + 907ad88 commit aba3e4a
Show file tree
Hide file tree
Showing 22 changed files with 982 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- The Plugin Store now displays plugin ratings and reviews. ([#15860](https://github.com/craftcms/cms/pull/15860))
- An `InvalidConfigException` is now thrown if the `defaultCountryCode` config setting is set to an empty string. ([#15812](https://github.com/craftcms/cms/pull/15812))
- Fixed an error that could occur when saving an element, if a Date field’s time zone input was focused.
- Fixed a bug where the time zones listed in Date fields weren’t labelled properly based on the selected date. ([#15805](https://github.com/craftcms/cms/issues/15805))
Expand Down
13 changes: 13 additions & 0 deletions src/translations/en/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
'All option labels must be unique.' => 'All option labels must be unique.',
'All option values must be unique.' => 'All option values must be unique.',
'All plugins must be compatible with Craft {version} before you can upgrade.' => 'All plugins must be compatible with Craft {version} before you can upgrade.',
'All reviews' => 'All Reviews',
'All targets must have a label.' => 'All targets must have a label.',
'All users' => 'All users',
'All' => 'All',
Expand Down Expand Up @@ -535,10 +536,12 @@
'Description' => 'Description',
'Deselect All' => 'Deselect All',
'Desktop' => 'Desktop',
'Developer Response' => 'Developer Response',
'Development Settings' => 'Development Settings',
'Development' => 'Development',
'Device type' => 'Device type',
'Dimensions' => 'Dimensions',
'Direction' => 'Direction',
'Directories cannot be deleted while moving assets.' => 'Directories cannot be deleted while moving assets.',
'Disable autofocus' => 'Disable autofocus',
'Disable focal point' => 'Disable focal point',
Expand Down Expand Up @@ -605,6 +608,7 @@
'Edit {type}' => 'Edit {type}',
'Edit “{title}”' => 'Edit “{title}”',
'Edit' => 'Edit',
'Edited {updated}' => 'Edited {updated}',
'Edited' => 'Edited',
'Eircode' => 'Eircode',
'Element' => 'Element',
Expand Down Expand Up @@ -655,6 +659,7 @@
'Export…' => 'Export…',
'External project config changes discarded.' => 'External project config changes discarded.',
'Failed to generate transform with id of {id}.' => 'Failed to generate transform with id of {id}.',
'Failed to load plugin reviews. Please try again' => 'Failed to load plugin reviews. Please try again',
'Failed to load the SVG string.' => 'Failed to load the SVG string.',
'Failed to save the image.' => 'Failed to save the image.',
'Failed' => 'Failed',
Expand Down Expand Up @@ -869,6 +874,7 @@
'Layout element types' => 'Layout element types',
'Learn how' => 'Learn how',
'Learn more' => 'Learn more',
'Leave a review' => 'Leave a review',
'Leave blank if categories don’t have URLs' => 'Leave blank if categories don’t have URLs',
'Leave blank if entries don’t have URLs' => 'Leave blank if entries don’t have URLs',
'Leave blank if the entry doesn’t have a URL' => 'Leave blank if the entry doesn’t have a URL',
Expand Down Expand Up @@ -1109,6 +1115,7 @@
'Options' => 'Options',
'Or use a password manager with built-in authentication support:' => 'Or use a password manager with built-in authentication support:',
'Orange' => 'Orange',
'Order by' => 'Order by',
'Organization Tax ID' => 'Organization Tax ID',
'Organization' => 'Organization',
'Orientation' => 'Orientation',
Expand Down Expand Up @@ -1237,6 +1244,8 @@
'Radio Button Options' => 'Radio Button Options',
'Radio Buttons' => 'Radio Buttons',
'Range…' => 'Range…',
'Rating' => 'Rating',
'Rating: {rating} out of {max} stars' => 'Rating: {rating} out of {max} stars',
'Raw data (fastest)' => 'Raw data (fastest)',
'Reactivate' => 'Reactivate',
'Ready to upgrade?' => 'Ready to upgrade?',
Expand Down Expand Up @@ -1320,6 +1329,7 @@
'Reverted content from revision {num}.' => 'Reverted content from revision {num}.',
'Reverting update (this may take a minute)…' => 'Reverting update (this may take a minute)…',
'Review' => 'Review',
'Reviews' => 'Reviews',
'Revision Notes' => 'Revision Notes',
'Revision {num}' => 'Revision {num}',
'Revision' => 'Revision',
Expand Down Expand Up @@ -1680,6 +1690,8 @@
'This license is tied to another Craft install. Visit {accountLink} to detach it, or buy a new license.' => 'This license is tied to another Craft install. Visit {accountLink} to detach it, or buy a new license.',
'This license isn’t allowed to run version {version}.' => 'This license isn’t allowed to run version {version}.',
'This month' => 'This month',
'This plugin doesn’t have any reviews with comments.' => 'This plugin doesn’t have any reviews with comments.',
'This plugin doesn’t have any reviews.' => 'This plugin doesn’t have any reviews.',
'This plugin is no longer maintained.' => 'This plugin is no longer maintained.',
'This plugin isn’t compatible with your version of Craft.' => 'This plugin isn’t compatible with your version of Craft.',
'This plugin requires Craft CMS {name} edition.' => 'This plugin requires Craft CMS {name} edition.',
Expand Down Expand Up @@ -2147,6 +2159,7 @@
'{total, number} {total, plural, =1{{item}} other{{items}}}' => '{total, number} {total, plural, =1{{item}} other{{items}}}',
'{total, number} {type} {total, plural, =1{field layout} other{field layouts}}' => '{total, number} {type} {total, plural, =1{field layout} other{field layouts}}',
'{totalItems, plural, =1{Item} other{Items}} moved.' => '{totalItems, plural, =1{Item} other{Items}} moved.',
'{totalReviews, plural, =1{# Review} other{# Reviews}}' => '{totalReviews, plural, =1{# Review} other{# Reviews}}',
'{total} jobs' => '{total} jobs',
'{total} updates available!' => '{total} updates available!',
'{type} Condition' => '{type} Condition',
Expand Down
14 changes: 14 additions & 0 deletions src/web/assets/pluginstore/PluginStoreAsset.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public function registerAssetFiles($view)
'Add all to cart',
'Add to cart',
'Added to cart',
'All reviews',
'Already in your cart',
'Ascending',
'Auto-renew for {price} annually, starting on {date}.',
Expand All @@ -78,11 +79,16 @@ public function registerAssetFiles($view)
'Couldn’t update item in cart.',
'Craft CMS edition changed.',
'Critical',
'Date Created',
'Descending',
'Developer Response',
'Direction',
'Discover',
'Documentation',
'Edited {updated}',
'Editions' => 'Editions',
'Everything in {edition}, plus…',
'Failed to load plugin reviews. Please try again',
'For everything else.',
'For marketing sites managed by small teams.',
'For personal sites built for yourself or a friend.',
Expand All @@ -96,6 +102,7 @@ public function registerAssetFiles($view)
'Items in your cart',
'Last Update',
'Last release',
'Leave a review',
'License',
'Licensed',
'Loading Plugin Store…',
Expand All @@ -105,23 +112,29 @@ public function registerAssetFiles($view)
'No results.',
'Only up to {version} is compatible with your version of Craft.',
'Open PRs',
'Order by',
'Overview',
'Page not found.',
'Plugin Store',
'Plugin edition changed.',
'Plus {renewalPrice}/year for updates after one year.',
'Popularity',
'Pricing',
'Rating',
'Rating: {rating} out of {max} stars',
'Reactivate',
'Remove',
'Report plugin',
'Repository',
'Reviews',
'Search plugins',
'See all',
'Showing results for “{searchQuery}”',
'The Plugin Store is not available, please try again later.',
'The developer recommends using <a href="{url}">{name}</a> instead.',
'This license is tied to another Craft install. Visit {accountLink} to detach it, or buy a new license.',
'This plugin doesn’t have any reviews with comments.',
'This plugin doesn’t have any reviews.',
'This plugin is no longer maintained.',
'This plugin isn’t compatible with your version of Craft.',
'This plugin requires Craft CMS {name} edition.',
Expand All @@ -140,6 +153,7 @@ public function registerAssetFiles($view)
'Website',
'Your cart is empty.',
'{num, number} {num, plural, =1{year} other{years}} of updates',
'{totalReviews, plural, =1{# Review} other{# Reviews}}',
]);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/web/assets/pluginstore/dist/css/app.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/pluginstore/dist/css/app.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/pluginstore/dist/js/app.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/web/assets/pluginstore/dist/js/app.js.map

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/web/assets/pluginstore/src/js/api/pluginstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export default {
params: {
withInstallHistory: true,
withIssueStats: true,
withReviewStats: true,
},
})
.then((responseData) => {
Expand Down Expand Up @@ -387,6 +388,16 @@ export default {
});
},

getPluginReviews(handle, params = {}) {
return api
.sendApiRequest('GET', `plugin/${handle}/reviews`, {params})
.catch((error) => {
if (!axios.isCancel(error)) {
console.error(error);
}
});
},

/**
* Get plugin index params.
*
Expand Down
18 changes: 18 additions & 0 deletions src/web/assets/pluginstore/src/js/components/PluginCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@
<div>{{ plugin.shortDescription }}</div>
</div>

<template
v-if="
plugin.totalReviews && plugin.totalReviews > 0 && plugin.ratingAvg
"
>
<div class="tw-flex tw-items-center tw-gap-1 tw-text-sm tw-mt-2 light">
<RatingStars :rating="plugin.ratingAvg" size="sm" />
({{ plugin.totalReviews }})
</div>
</template>

<template v-if="plugin.abandoned">
<div class="error">{{ 'Abandoned' | t('app') }}</div>
</template>
Expand All @@ -57,11 +68,13 @@
import {mapGetters} from 'vuex';
import EditionBadge from './EditionBadge';
import RatingStars from '../components/RatingStars.vue';
export default {
props: ['plugin', 'trialMode'],
components: {
RatingStars,
EditionBadge,
},
Expand Down Expand Up @@ -150,6 +163,11 @@
}
}
.plugin-rating {
display: flex;
align-items: center;
}
a.plugin-card {
box-sizing: border-box;
@apply tw-text-gray-900;
Expand Down
16 changes: 14 additions & 2 deletions src/web/assets/pluginstore/src/js/components/PluginLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@
slug: '',
});
tabs.push({
name: this.$options.filters.t('Reviews', 'app'),
slug: 'reviews',
});
if (
!this.isPluginFree(this.plugin) &&
this.plugin.editions.length > 1
Expand Down Expand Up @@ -141,8 +146,15 @@
this.$store.commit('pluginStore/updatePluginDetails', null);
this.$store
.dispatch('pluginStore/getPluginDetailsByHandle', pluginHandle)
Promise.all([
this.$store.dispatch('pluginReviews/getPluginReviews', {
handle: pluginHandle,
}),
this.$store.dispatch(
'pluginStore/getPluginDetailsByHandle',
pluginHandle
),
])
.then(() => {
this.loading = false;
})
Expand Down
4 changes: 4 additions & 0 deletions src/web/assets/pluginstore/src/js/components/PluginMeta.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
<dl class="tw-mt-2">
<install-plugin :plugin="plugin" />

<PluginRatingStat :plugin="plugin" :stats="plugin.reviewStats" />

<active-installs :plugin="plugin" />

<div class="tw-grid tw-grid-cols-2">
Expand Down Expand Up @@ -236,6 +238,7 @@
import InstallPlugin from './InstallPlugin';
import GithubActivity from './github-activity/GithubActivity';
import ActiveInstalls from './ActiveInstalls';
import PluginRatingStat from './PluginRatingStat.vue';
export default {
data() {
Expand All @@ -246,6 +249,7 @@
};
},
components: {
PluginRatingStat,
InstallPlugin,
ActiveInstalls,
GithubActivity,
Expand Down
105 changes: 105 additions & 0 deletions src/web/assets/pluginstore/src/js/components/PluginRatingStat.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<script>
/* global Craft */
import {defineComponent} from 'vue';
import Stat from './Stat.vue';
import RatingStars from './RatingStars.vue';
export default defineComponent({
components: {
RatingStars,
Stat,
},
name: 'PluginRatingStat',
methods: {
getPluginReviewUrl(handle) {
if (!handle) {
return '';
}
return `https://console.craftcms.com/accounts/me/plugin-store/reviews/${this.plugin.handle}`;
},
},
computed: {
headingText() {
return Craft.t(
'app',
'{totalReviews, plural, =1{# Review} other{# Reviews}}',
{
totalReviews: this.stats.totalReviews,
}
);
},
},
props: {
stats: Object,
plugin: Object,
},
});
</script>

<template>
<div>
<div v-if="stats">
<Stat>
<template #title>
<div class="tw-flex tw-items-baseline tw-justify-between">
{{ headingText }}
<router-link
v-if="stats.totalReviews > 0"
:to="`${plugin?.handle}/reviews`"
class="tw-text-xs"
>
{{ 'All reviews' | t('app') }}
</router-link>
</div>
</template>
<template #content>
<div v-if="stats.totalReviews > 0">
<div class="tw-flex tw-items-center tw-gap-3 tw-mt-2">
<div class="tw-flex tw-items-baseline tw-gap-1 tw-relative">
<span class="tw-text-3xl tw-font-normal">{{
stats.ratingAvg
}}</span>
<span class="tw-text-sm tw-text-gray-500 dark:tw-text-gray-400"
>/ 5</span
>
</div>
<div class="tw-flex tw-items-center tw-gap-1">
<RatingStars size="lg" :rating="stats.ratingAvg" />
</div>
</div>
<div
class="tw-flex tw-items-baseline tw-text-sm tw-mt-4 tw-gap-4 tw-text-gray-300"
>
<a :href="getPluginReviewUrl(plugin?.handle)">{{
'Leave a review' | t('app')
}}</a>
</div>
</div>
</template>
</Stat>
</div>
<div v-else>
<Stat>
<template #title>Reviews</template>
<template #content>
<p class="tw-font-normal">
{{ 'This plugin doesn’t have any reviews.' | t('app') }}
</p>

<div class="tw-mt-2">
<c-btn
block
target="_blank"
:href="getPluginReviewUrl(plugin?.handle)"
>
{{ 'Leave a review' | t('app') }}
</c-btn>
</div>
</template>
</Stat>
</div>
</div>
</template>

<style scoped lang="scss"></style>
Loading

0 comments on commit aba3e4a

Please sign in to comment.