Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IAPS Reviews #15860

Merged
merged 7 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -86,6 +86,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 @@ -511,10 +512,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 focal point' => 'Disable focal point',
'Disable' => 'Disable',
Expand Down Expand Up @@ -575,6 +578,7 @@
'Edit “{entryType}”' => 'Edit “{entryType}”',
'Edit “{title}”' => 'Edit “{title}”',
'Edit' => 'Edit',
'Edited {updated}' => 'Edited {updated}',
'Edited' => 'Edited',
'Eircode' => 'Eircode',
'Element' => 'Element',
Expand Down Expand Up @@ -621,6 +625,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 @@ -826,6 +831,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 @@ -1054,6 +1060,7 @@
'Optgroup?' => 'Optgroup?',
'Option Label' => 'Option Label',
'Options' => 'Options',
'Order by' => 'Order by',
'Organization Tax ID' => 'Organization Tax ID',
'Organization' => 'Organization',
'Orientation' => 'Orientation',
Expand Down Expand Up @@ -1156,6 +1163,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 @@ -1232,6 +1241,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 @@ -1561,6 +1571,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 PHP {v1}, but your composer.json file is currently set to {v2}.' => 'This plugin requires PHP {v1}, but your composer.json file is currently set to {v2}.',
Expand Down Expand Up @@ -1991,6 +2003,7 @@
'{title} ({site})' => '{title} ({site})',
'{total, number} {total, plural, =1{{item}} other{{items}}}' => '{total, number} {total, plural, =1{{item}} other{{items}}}',
'{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,10 +79,15 @@ 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',
'Failed to load plugin reviews. Please try again',
'For when you’re building a website for yourself or a friend.',
'For when you’re building something professionally for a client or team.',
'Free',
Expand All @@ -95,6 +101,7 @@ public function registerAssetFiles($view)
'Items in your cart',
'Last Update',
'Last release',
'Leave a review',
'License',
'Licensed',
'Loading Plugin Store…',
Expand All @@ -104,22 +111,28 @@ 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.',
'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 PHP {v1}, but your composer.json file is currently set to {v2}.',
Expand All @@ -138,6 +151,7 @@ public function registerAssetFiles($view)
'Your cart is empty.',
'{num, number} {num, plural, =1{year} other{years}} of updates',
'{renewalPrice}/year per site for updates after that.',
'{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