Skip to content

Commit fda8398

Browse files
committed
Add recommendations announcement
1 parent 502b5ce commit fda8398

5 files changed

Lines changed: 184 additions & 5 deletions

File tree

contentcuration/contentcuration/frontend/channelEdit/views/CurrentTopicView.vue

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
fluid
66
class="ma-0 main pa-0 panel"
77
>
8+
<AiRecommendationsBanner
9+
v-if="canEdit"
10+
:dismissible="true"
11+
class="recommendations-announcement"
12+
>
13+
<KRouterLink
14+
appearance="flat-button"
15+
:primary="true"
16+
:to="importFromChannelsRoute"
17+
class="recommendations-announcement-cta"
18+
@click="trackClickEvent('View recommendations')"
19+
>
20+
{{ searchRecommendationsStrings.viewRecommendationsButton$() }}
21+
</KRouterLink>
22+
</AiRecommendationsBanner>
23+
824
<!-- Breadcrumbs -->
925
<VToolbar
1026
dense
@@ -306,6 +322,8 @@
306322
import { DraggableTypes, DropEffect } from 'shared/mixins/draggable/constants';
307323
import { DraggableFlags } from 'shared/vuex/draggablePlugin/module/constants';
308324
import DraggableRegion from 'shared/views/draggable/DraggableRegion';
325+
import { searchRecommendationsStrings } from 'shared/strings/searchRecommendationsStrings';
326+
import AiRecommendationsBanner from 'shared/views/AiRecommendationsBanner';
309327
310328
export default {
311329
name: 'CurrentTopicView',
@@ -320,8 +338,12 @@
320338
MoveModal,
321339
DraggableRegion,
322340
InheritAncestorMetadataModal,
341+
AiRecommendationsBanner,
323342
},
324343
mixins: [titleMixin, routerMixin],
344+
setup() {
345+
return { searchRecommendationsStrings };
346+
},
325347
props: {
326348
topicId: {
327349
type: String,
@@ -1075,4 +1097,12 @@
10751097
flex-shrink: 0;
10761098
}
10771099
1100+
.recommendations-announcement {
1101+
margin: 24px 36px;
1102+
}
1103+
1104+
.recommendations-announcement-cta {
1105+
margin-top: 12px;
1106+
}
1107+
10781108
</style>

contentcuration/contentcuration/frontend/channelList/views/Channel/StudioChannelsPage/index.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22

33
<div class="channels-page">
4+
<AiRecommendationsBanner class="recommendations-announcement" />
45
<StudioRaisedBox
56
v-if="invitations.length"
67
class="invitations"
@@ -56,12 +57,14 @@
5657
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
5758
import ChannelInvitation from '../ChannelInvitation';
5859
import StudioRaisedBox from 'shared/views/StudioRaisedBox';
60+
import AiRecommendationsBanner from 'shared/views/AiRecommendationsBanner';
5961
6062
export default {
6163
name: 'StudioChannelsPage',
6264
components: {
6365
ChannelInvitation,
6466
StudioRaisedBox,
67+
AiRecommendationsBanner,
6568
},
6669
setup() {
6770
const { windowBreakpoint } = useKResponsiveWindow();
@@ -129,6 +132,7 @@
129132
130133
.channels-page {
131134
padding-bottom: 24px;
135+
margin: auto;
132136
}
133137
134138
.channels,
@@ -138,6 +142,7 @@
138142
}
139143
140144
.invitations {
145+
margin-top: 24px; // added for space between search recs announcement and invitations box
141146
margin-bottom: 24px;
142147
}
143148
@@ -149,4 +154,9 @@
149154
margin-top: 16px;
150155
}
151156
157+
.recommendations-announcement {
158+
max-width: 900px;
159+
margin: auto;
160+
}
161+
152162
</style>

contentcuration/contentcuration/frontend/shared/strings/searchRecommendationsStrings.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import { createTranslator } from 'shared/i18n';
22

33
export const searchRecommendationsStrings = createTranslator('SearchRecommendationsStrings', {
4+
trySearchRecommendationsHeader: {
5+
message: "Try our new 'Recommendations' feature!",
6+
context: 'Header for a banner announcing the new recommendations feature',
7+
},
8+
trySearchRecommendationsText: {
9+
message:
10+
"Based on the title and descriptions of your folders, we'll suggest content from the Kolibri Library. Choose 'Import from channels' in any channel folder to see your recommendations.",
11+
context: 'Body text for a banner announcing the new recommendations feature',
12+
},
13+
viewRecommendationsButton: {
14+
message: 'View recommendations',
15+
context: 'Label for a button that takes the user to the recommendations feature',
16+
},
417
aboutRecommendationsText: {
518
message: 'About recommendations',
619
context: 'A title that introduces how the recommendation system works',
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<template>
2+
3+
<StudioBanner
4+
v-if="!dismissed"
5+
:style="{
6+
backgroundColor: $themePalette.blue.v_100,
7+
padding: '20px',
8+
gap: '20px',
9+
borderRadius: '4px',
10+
}"
11+
>
12+
<template #icon>
13+
<div
14+
class="icon-wrapper"
15+
:style="{ backgroundColor: $themePalette.blue.v_200 }"
16+
>
17+
<KIcon
18+
icon="library"
19+
class="icon"
20+
:color="$themePalette.white"
21+
:style="{ backgroundColor: $themePalette.blue.v_400 }"
22+
/>
23+
</div>
24+
</template>
25+
26+
<div class="content">
27+
<div class="text">
28+
<h2>
29+
{{ searchRecommendationsStrings.trySearchRecommendationsHeader$() }}
30+
</h2>
31+
<p>
32+
{{ searchRecommendationsStrings.trySearchRecommendationsText$() }}
33+
</p>
34+
</div>
35+
<slot></slot>
36+
</div>
37+
38+
<KIconButton
39+
v-if="dismissible"
40+
icon="close"
41+
:tooltip="searchRecommendationsStrings.closeAction$()"
42+
class="dismiss-btn"
43+
@click="dismiss"
44+
/>
45+
</StudioBanner>
46+
47+
</template>
48+
49+
50+
<script>
51+
52+
import StudioBanner from 'shared/views/StudioBanner';
53+
import { searchRecommendationsStrings } from 'shared/strings/searchRecommendationsStrings';
54+
55+
const DISMISSED_KEY = 'recommendations-announcement-dismissed';
56+
57+
export default {
58+
name: 'AiRecommendationsBanner',
59+
components: { StudioBanner },
60+
setup() {
61+
return { searchRecommendationsStrings };
62+
},
63+
props: {
64+
dismissible: {
65+
type: Boolean,
66+
default: false,
67+
},
68+
},
69+
data() {
70+
return {
71+
dismissed: localStorage.getItem(DISMISSED_KEY) === 'true',
72+
};
73+
},
74+
methods: {
75+
dismiss() {
76+
localStorage.setItem(DISMISSED_KEY, 'true');
77+
this.dismissed = true;
78+
},
79+
},
80+
};
81+
82+
</script>
83+
84+
85+
<style lang="scss" scoped>
86+
87+
.icon-wrapper {
88+
display: flex;
89+
flex-shrink: 0;
90+
align-items: center;
91+
justify-content: center;
92+
width: 96px;
93+
height: 96px;
94+
border-radius: 2px;
95+
}
96+
97+
.icon {
98+
width: 40px;
99+
height: 40px;
100+
padding: 6px;
101+
border-radius: 50%;
102+
}
103+
104+
.content {
105+
display: flex;
106+
flex: 1;
107+
flex-direction: column;
108+
align-items: flex-end;
109+
110+
p {
111+
margin: 0;
112+
}
113+
}
114+
115+
h2 {
116+
font-size: 18px;
117+
}
118+
119+
.dismiss-btn {
120+
flex-shrink: 0;
121+
align-self: flex-start;
122+
}
123+
124+
</style>

contentcuration/contentcuration/frontend/shared/views/StudioBanner.vue

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
backgroundColor: error ? $themePalette.red.v_100 : '',
88
}"
99
>
10-
<KIcon
11-
v-if="error"
12-
class="icon"
13-
icon="error"
14-
/>
10+
<slot name="icon">
11+
<KIcon
12+
v-if="error"
13+
class="icon"
14+
icon="error"
15+
/>
16+
</slot>
1517
<slot>
1618
{{ text }}
1719
</slot>

0 commit comments

Comments
 (0)