Skip to content

Commit f9a9b51

Browse files
authored
Merge pull request #238 from TechnologyEnhancedLearning/Develop/Features/TD-3285-feature_flag_functionality_for_ams_contents
Develop/features/td 3285 feature flag functionality for ams contents
2 parents 93eefb5 + 8646677 commit f9a9b51

32 files changed

+440
-91
lines changed

AdminUI/LearningHub.Nhs.AdminUI/Controllers/ResourceController.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77
using LearningHub.Nhs.AdminUI.Configuration;
88
using LearningHub.Nhs.AdminUI.Extensions;
9+
using LearningHub.Nhs.AdminUI.Helpers;
910
using LearningHub.Nhs.AdminUI.Interfaces;
1011
using LearningHub.Nhs.AdminUI.Models;
1112
using LearningHub.Nhs.Models.Common;
@@ -16,6 +17,7 @@
1617
using Microsoft.AspNetCore.Mvc;
1718
using Microsoft.Extensions.Logging;
1819
using Microsoft.Extensions.Options;
20+
using Microsoft.FeatureManagement;
1921

2022
/// <summary>
2123
/// Defines the <see cref="ResourceController" />.
@@ -32,6 +34,11 @@ public class ResourceController : BaseController
3234
/// </summary>
3335
private readonly IOptions<WebSettings> websettings;
3436

37+
/// <summary>
38+
/// Defines the featureManager.
39+
/// </summary>
40+
private readonly IFeatureManager featureManager;
41+
3542
/// <summary>
3643
/// Defines the _logger.
3744
/// </summary>
@@ -55,18 +62,21 @@ public class ResourceController : BaseController
5562
/// <param name="logger">The logger<see cref="ILogger{HomeController}"/>.</param>
5663
/// <param name="resourceService">The resourceService<see cref="IResourceService"/>.</param>
5764
/// /// <param name="websettings">The websettings<see cref="IOptions{WebSettings}"/>.</param>
65+
/// <param name="featureManager">The featureManager<see cref="IFeatureManager"/>.</param>
5866
public ResourceController(
5967
IWebHostEnvironment hostingEnvironment,
6068
IOptions<WebSettings> config,
6169
ILogger<HomeController> logger,
6270
IResourceService resourceService,
63-
IOptions<WebSettings> websettings)
71+
IOptions<WebSettings> websettings,
72+
IFeatureManager featureManager)
6473
: base(hostingEnvironment)
6574
{
6675
this.logger = logger;
6776
this.websettings = websettings;
6877
this.config = config.Value;
6978
this.resourceService = resourceService;
79+
this.featureManager = featureManager;
7080
}
7181

7282
/// <summary>
@@ -309,6 +319,33 @@ public async Task<IActionResult> Unpublish(int resourceVersionId, string details
309319
}
310320
}
311321

322+
/// <summary>
323+
/// The GetAVUnavailableView.
324+
/// </summary>
325+
/// <returns> partial view. </returns>
326+
[Route("Resource/GetAVUnavailableView")]
327+
[HttpGet("GetAVUnavailableView")]
328+
public IActionResult GetAVUnavailableView()
329+
{
330+
return this.PartialView("_AudioVideoUnavailable");
331+
}
332+
333+
/// <summary>
334+
/// The GetAddAVFlag.
335+
/// </summary>
336+
/// <returns> Return AV Flag.</returns>
337+
[Route("Resource/GetAddAVFlag")]
338+
[HttpGet("GetAddAVFlag")]
339+
public bool GetAddAVFlag() => this.featureManager.IsEnabledAsync(FeatureFlags.AddAudioVideo).Result;
340+
341+
/// <summary>
342+
/// The GetDisplayAVFlag.
343+
/// </summary>
344+
/// <returns> Return display AV flag.</returns>
345+
[Route("Resource/GetDisplayAVFlag")]
346+
[HttpGet("GetDisplayAVFlag")]
347+
public bool GetDisplayAVFlag() => this.featureManager.IsEnabledAsync(FeatureFlags.DisplayAudioVideo).Result;
348+
312349
private static List<PagingOptionPair> FilterOptions()
313350
{
314351
List<PagingOptionPair> options = new List<PagingOptionPair>();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace LearningHub.Nhs.AdminUI.Helpers
2+
{
3+
/// <summary>
4+
/// <see cref="FeatureFlags"/>.
5+
/// </summary>
6+
public static class FeatureFlags
7+
{
8+
/// <summary>
9+
/// The AddAudioVideo.
10+
/// </summary>
11+
public const string AddAudioVideo = "AddAudioVideo";
12+
13+
/// <summary>
14+
/// The DisplayAudioVideo.
15+
/// </summary>
16+
public const string DisplayAudioVideo = "DisplayAudioVideo";
17+
}
18+
}

AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@
9494
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.0" />
9595
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0" />
9696
<PackageReference Include="Microsoft.Azure.Management.Media" Version="5.0.0" />
97+
<PackageReference Include="Microsoft.FeatureManagement" Version="3.2.0" />
98+
<PackageReference Include="Microsoft.FeatureManagement.AspNetCore" Version="3.2.0" />
9799
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.9" />
98100
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.14.1" />
99101
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.14.1" />

AdminUI/LearningHub.Nhs.AdminUI/Scripts/vuesrc/content/cmsPageRow.vue

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<div v-html="getDescription" />
1919
</div>
2020
<div class="information-page__asset-container">
21-
<div id="mediaContainer" :class="[`${disableVideoControl ? 'videoControlDisabled' : ''}`]" v-show="sectionTemplateType === SectionTemplateType.Video" class="w-100">
21+
<div id="mediaContainer" :class="[`${disableVideoControl ? 'videoControlDisabled' : ''}`]" v-show="sectionTemplateType === SectionTemplateType.Video && displayAVFlag" class="w-100">
2222
<video controls v-show="section.id" :id="[`azureMediaPlayer${section.id}`]"
2323
data-setup='{"logo": { "enabled": false }, "techOrder": ["azureHtml5JS", "flashSS", "silverlightSS", "html5"], "nativeControlsForTouch": false, "fluid": true}'
2424
class="azuremediaplayer amp-default-skin amp-big-play-centered" style="height:250px;">
@@ -33,6 +33,9 @@
3333
</div>
3434
</div>
3535
</div>
36+
<div v-if="!displayAVFlag">
37+
<div v-html="audioVideoUnavailableView"></div>
38+
</div>
3639
</div>
3740
<div v-if="sectionTemplateType === SectionTemplateType.Image && section.imageAsset" class="nhsuk-grid-column-full">
3841
<div :class="[`information-page__container ${section.sectionLayoutType == SectionLayoutType.Left ? 'information-page__container--reverse-child-order' : '' } ${section.hasBorder ? 'information-page__container--border' : '' }`]">
@@ -78,10 +81,14 @@
7881
SectionTemplateType: SectionTemplateType,
7982
pageSectionDetail: null as PageSectionDetailModel,
8083
disableVideoControl: false,
84+
displayAVFlag: false,
85+
audioVideoUnavailableView : '' as string,
8186
};
8287
},
8388
created() {
8489
this.load();
90+
this.getDisplayAVFlag();
91+
this.getAudioVideoUnavailableView();
8592
},
8693
computed: {
8794
getStyle() {
@@ -125,7 +132,7 @@
125132
returnClass = "information-page__text-container--no-padding-right";
126133
}
127134
}
128-
return returnClass;
135+
return returnClass;
129136
},
130137
getDescription() {
131138
if (this.section.description) {
@@ -138,50 +145,60 @@
138145
},
139146
isRightSectionLayout() {
140147
return this.section.sectionLayoutType == SectionLayoutType.Right;
141-
}
148+
},
142149
},
143150
methods: {
151+
getDisplayAVFlag() {
152+
contentData.getDisplayAVFlag().then(response => {
153+
this.displayAVFlag = response;
154+
});
155+
},
156+
getAudioVideoUnavailableView() {
157+
contentData.getAVUnavailableView().then(response => {
158+
this.audioVideoUnavailableView = response;
159+
});
160+
},
144161
load() {
145162
if (this.sectionTemplateType === SectionTemplateType.Video) {
146-
contentData.getPageSectionDetailVideo(this.section.id).then(response => {
147-
this.pageSectionDetail = response;
163+
contentData.getPageSectionDetailVideo(this.section.id).then(response => {
164+
this.pageSectionDetail = response;
148165
149-
if (!this.pageSectionDetail.videoAsset)
150-
return;
166+
if (!this.pageSectionDetail.videoAsset)
167+
return;
151168
152-
const id = 'azureMediaPlayer' + this.pageSectionDetail.id;
153-
let azureMediaPlayer = amp(id);
169+
const id = 'azureMediaPlayer' + this.pageSectionDetail.id;
170+
let azureMediaPlayer = amp(id);
154171
155-
if (this.pageSectionDetail.videoAsset.azureMediaAsset) {
156-
$(`#${id}`).css({ 'height': '', 'border': '1px solid #768692' });
157-
this.disableVideoControl = false;
158-
} else {
159-
this.disableVideoControl = true;
160-
}
172+
if (this.pageSectionDetail.videoAsset.azureMediaAsset) {
173+
$(`#${id}`).css({ 'height': '', 'border': '1px solid #768692' });
174+
this.disableVideoControl = false;
175+
} else {
176+
this.disableVideoControl = true;
177+
}
161178
162-
if (this.pageSectionDetail.videoAsset.thumbnailImageFile) {
163-
azureMediaPlayer.poster(`/file/download/${this.pageSectionDetail.videoAsset.thumbnailImageFile.filePath}/${this.pageSectionDetail.videoAsset.thumbnailImageFile.fileName}`);
164-
}
165-
if (this.pageSectionDetail.videoAsset.azureMediaAsset && this.pageSectionDetail.videoAsset.closedCaptionsFile) {
166-
azureMediaPlayer.src([{
167-
type: "application/vnd.ms-sstr+xml",
168-
src: this.pageSectionDetail.videoAsset.azureMediaAsset.locatorUri,
169-
protectionInfo: [{ type: 'AES', authenticationToken: `Bearer=${this.pageSectionDetail.videoAsset.azureMediaAsset.authenticationToken}` }]
170-
}],
171-
[{ kind: "captions", src: `/file/download/${this.pageSectionDetail.videoAsset.closedCaptionsFile.filePath}/${this.pageSectionDetail.videoAsset.closedCaptionsFile.fileName}`, srclang: "en", label: "english" }]);
172-
}
173-
else if (this.pageSectionDetail.videoAsset.azureMediaAsset && !this.pageSectionDetail.videoAsset.closedCaptionsFile) {
174-
azureMediaPlayer.src([{
175-
type: "application/vnd.ms-sstr+xml",
176-
src: this.pageSectionDetail.videoAsset.azureMediaAsset.locatorUri,
177-
protectionInfo: [{ type: 'AES', authenticationToken: `Bearer=${this.pageSectionDetail.videoAsset.azureMediaAsset.authenticationToken}` }]
178-
}]);
179-
}
180-
});
181-
} else {
182-
contentData.getPageSectionDetail(this.section.id).then(x => this.pageSectionDetail = x);
183-
}
184-
},
179+
if (this.pageSectionDetail.videoAsset.thumbnailImageFile) {
180+
azureMediaPlayer.poster(`/file/download/${this.pageSectionDetail.videoAsset.thumbnailImageFile.filePath}/${this.pageSectionDetail.videoAsset.thumbnailImageFile.fileName}`);
181+
}
182+
if (this.pageSectionDetail.videoAsset.azureMediaAsset && this.pageSectionDetail.videoAsset.closedCaptionsFile) {
183+
azureMediaPlayer.src([{
184+
type: "application/vnd.ms-sstr+xml",
185+
src: this.pageSectionDetail.videoAsset.azureMediaAsset.locatorUri,
186+
protectionInfo: [{ type: 'AES', authenticationToken: `Bearer=${this.pageSectionDetail.videoAsset.azureMediaAsset.authenticationToken}` }]
187+
}],
188+
[{ kind: "captions", src: `/file/download/${this.pageSectionDetail.videoAsset.closedCaptionsFile.filePath}/${this.pageSectionDetail.videoAsset.closedCaptionsFile.fileName}`, srclang: "en", label: "english" }]);
189+
}
190+
else if (this.pageSectionDetail.videoAsset.azureMediaAsset && !this.pageSectionDetail.videoAsset.closedCaptionsFile) {
191+
azureMediaPlayer.src([{
192+
type: "application/vnd.ms-sstr+xml",
193+
src: this.pageSectionDetail.videoAsset.azureMediaAsset.locatorUri,
194+
protectionInfo: [{ type: 'AES', authenticationToken: `Bearer=${this.pageSectionDetail.videoAsset.azureMediaAsset.authenticationToken}` }]
195+
}]);
196+
}
197+
});
198+
} else {
199+
contentData.getPageSectionDetail(this.section.id).then(x => this.pageSectionDetail = x);
200+
}
201+
},
185202
getAESProtection(token: string): string {
186203
var aesProtectionInfo = '{"protectionInfo": [{"type": "AES", "authenticationToken":"Bearer=' + token + '"}], "streamingFormats":["SMOOTH","DASH"]}';
187204
return aesProtectionInfo;
@@ -198,7 +215,7 @@
198215
},
199216
watch: {
200217
section() {
201-
this.load();
218+
this.load();
202219
}
203220
}
204221
})

AdminUI/LearningHub.Nhs.AdminUI/Scripts/vuesrc/content/contentState.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ export class State {
2525
isVideoFileValid: boolean;
2626
isTranscriptFileValid: boolean;
2727
isCaptionFileValid: boolean;
28-
isThumbnailFileValid: boolean;
28+
isThumbnailFileValid: boolean;
29+
getAVUnavailableView: string = '';
2930
}
3031
const state = new State();
3132

@@ -37,7 +38,10 @@ class ApiRequest {
3738
const mutations = {
3839
async populateUploadSettings(state: State) {
3940
state.uploadSettings = await contentData.getUploadSettings();
40-
},
41+
},
42+
async populateAVUnavailableView(state: State) {
43+
state.getAVUnavailableView = await contentData.getAVUnavailableView();
44+
},
4145
setCurrentUserName(state: State, payload: string) {
4246
state.currentUserName = payload;
4347
},

AdminUI/LearningHub.Nhs.AdminUI/Scripts/vuesrc/content/pageVideoSection.vue

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@
6666
</div>
6767
</div>
6868

69-
<div>
69+
<div v-if="!addAVFlag">
70+
<label class="control-label">Feature Video</label>
71+
<div v-html="audioVideoUnavailableView"></div>
72+
</div>
73+
74+
<div v-else>
7075
<label class="control-label">Feature Video</label>
7176
<div>
7277
<span class="text-secondary mb-5">
@@ -284,7 +289,8 @@ Vue.use(Vuelidate as any);
284289
deleteWarning: false,
285290
fileDeleteWarning: false,
286291
fileOrTypeToBeDeleted: 0,
287-
videoErrorMessage: ''
292+
videoErrorMessage: '',
293+
addAVFlag: false
288294
}
289295
},
290296
validations: {
@@ -294,7 +300,9 @@ Vue.use(Vuelidate as any);
294300
}
295301
},
296302
async created() {
297-
this.$store.commit('populateUploadSettings');
303+
this.$store.commit('populateUploadSettings');
304+
this.$store.commit('populateAVUnavailableView');
305+
this.getAddAudioVideoFlag();
298306
299307
const pageSectionId = this.$route.params.sectionId;
300308
@@ -348,7 +356,10 @@ Vue.use(Vuelidate as any);
348356
},
349357
videoAsset(): VideoAssetModel {
350358
return this.$store.state.pageSectionDetail.videoAsset;
351-
}
359+
},
360+
audioVideoUnavailableView(): string {
361+
return this.$store.state.getAVUnavailableView;
362+
},
352363
},
353364
methods: {
354365
setSectionLayoutType(sectionLayoutType: SectionLayoutType) {
@@ -492,7 +503,12 @@ Vue.use(Vuelidate as any);
492503
this.fileErrorType = FileErrorTypeEnum.NoError
493504
this.fileUploadServerError = '';
494505
$('#fileUpload').val(null);
495-
},
506+
},
507+
getAddAudioVideoFlag() {
508+
contentData.getAddAVFlag().then(response => {
509+
this.addAVFlag = response;
510+
});
511+
},
496512
},
497513
});
498514
</script>

AdminUI/LearningHub.Nhs.AdminUI/Scripts/vuesrc/data/content.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,38 @@ const updateVideoAsset = async function (videoAsset: VideoAssetModel): Promise<b
241241
});
242242
};
243243

244+
const getAddAVFlag = async function (): Promise<boolean> {
245+
return await axios.get<boolean>('/Resource/GetAddAVFlag')
246+
.then(response => {
247+
return response.data;
248+
})
249+
.catch(e => {
250+
console.log('getAddAVFlag:' + e);
251+
throw e;
252+
});
253+
};
254+
255+
const getDisplayAVFlag = async function (): Promise<boolean> {
256+
return await axios.get<boolean>('/Resource/GetDisplayAVFlag')
257+
.then(response => {
258+
return response.data;
259+
})
260+
.catch(e => {
261+
console.log('getDisplayAVFlag:' + e);
262+
throw e;
263+
});
264+
};
265+
266+
const getAVUnavailableView = async function (): Promise<string> {
267+
return await axios.get('/Resource/GetAVUnavailableView')
268+
.then(response => {
269+
return response.data;
270+
})
271+
.catch(e => {
272+
console.error('Error fetching shared partial view:', e)
273+
throw e;
274+
});
275+
};
244276

245277
export const contentData = {
246278
getUploadSettings,
@@ -260,5 +292,8 @@ export const contentData = {
260292
createPageSection,
261293
updatePageSectionDetail,
262294
getPageSectionDetailVideo,
263-
updateVideoAsset
295+
updateVideoAsset,
296+
getAddAVFlag,
297+
getDisplayAVFlag,
298+
getAVUnavailableView
264299
};

0 commit comments

Comments
 (0)