Skip to content

Commit

Permalink
Merge branch 'next' into ui-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Maria-C1 authored Oct 9, 2024
2 parents 3e9866c + 0dbff12 commit 4305713
Show file tree
Hide file tree
Showing 15 changed files with 579 additions and 24 deletions.
53 changes: 35 additions & 18 deletions .github/workflows/contentful-schema-migrate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ on:
inputs:
target_environment:
required: true
type: string

env:
MANAGEMENT_TOKEN: ${{ secrets.CONTENTFUL_MANAGEMENT_TOKEN }}
DELIVERY_KEY: ${{ secrets.TF_VAR_CPD_DELIVERY_KEY }}
SPACE_ID: ${{ secrets.TF_VAR_CPD_SPACE_ID }}
ENVIRONMENT: ${{ inputs.target_environment }}
SPACE_CAPACITY: ${{ vars.CONTENTFUL_SPACE_CAPACITY }}
default: 'dev'
type: choice
options:
- dev
- test
- prod

jobs:
setup:
runs-on: ubuntu-latest
environment: ${{inputs.target_environment}}

env:
MANAGEMENT_TOKEN: ${{ secrets.CONTENTFUL_MANAGEMENT_TOKEN }}
DELIVERY_KEY: ${{ secrets.TF_VAR_CPD_DELIVERY_KEY }}
ENVIRONMENT: ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }}
SPACE_CAPACITY: ${{ vars.CONTENTFUL_SPACE_CAPACITY }}
SPACE_ID: ${{ secrets.TF_VAR_CPD_SPACE_ID }}

outputs:
staging-environment: ${{ steps.staging-env.outputs.staging-environment }}
Expand All @@ -33,21 +39,21 @@ jobs:
working-directory: ./Contentful-Schema
run: npm ci

- name: Verify contentful space has available environment capacity
working-directory: ./Contentful-Schema/utils
run: node verify-space-capacity.js

- name: Get target environment current migration version
id: current-migration-version
working-directory: ./Contentful-Schema/utils
run: node get-environment-version.js

- name: Verify contentful space has available environment capacity
working-directory: ./Contentful-Schema/utils
run: node verify-space-capacity.js

- name: Determine timestamp for new staging environment
run: echo "TIMESTAMP=$(date +%Y-%m-%d-%H-%M-%S)" >> $GITHUB_ENV

- name: Set var for name of new environment
id: staging-env
run: echo "staging-environment=$(echo ${{ inputs.target_environment }}-${{ env.TIMESTAMP }})" >> $GITHUB_OUTPUT
run: echo "staging-environment=$(echo ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }}-${{ env.TIMESTAMP }})" >> $GITHUB_OUTPUT

- name: Extract migration files from archive
working-directory: ./Contentful-Schema/migrations
Expand All @@ -66,19 +72,23 @@ jobs:
if: ${{ join(needs.setup.outputs.required-migrations, '') != '[]' }}
needs: [setup]
runs-on: ubuntu-latest
steps:

env:
MANAGEMENT_TOKEN: ${{ secrets.CONTENTFUL_MANAGEMENT_TOKEN }}
SPACE_ID: ${{ secrets.TF_VAR_CPD_SPACE_ID }}

steps:
- name: Install Contentful CLI
run: npm install -g contentful-cli

- name: Login to Contentful with management token
run: contentful login --management-token "${{ env.MANAGEMENT_TOKEN }}"

- name: Set target space
run: contentful space use --space-id ${{ env.SPACE_ID }} --environment-id ${{ inputs.target_environment }}
run: contentful space use --space-id ${{ env.SPACE_ID }} --environment-id ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }}

- name: Clone target environment ${{ inputs.target_environment }} to staging environment ${{ needs.setup.outputs.staging-environment }}
run: contentful space environment create --name ${{ needs.setup.outputs.staging-environment }} --environment-id ${{ needs.setup.outputs.staging-environment }} --source ${{ inputs.target_environment }}
- name: Clone target environment ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }} to staging environment ${{ needs.setup.outputs.staging-environment }}
run: contentful space environment create --name ${{ needs.setup.outputs.staging-environment }} --environment-id ${{ needs.setup.outputs.staging-environment }} --source ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }}

migrate:
if: ${{ join(needs.setup.outputs.required-migrations, '') != '[]' }}
Expand All @@ -89,6 +99,10 @@ jobs:
matrix:
value: ${{fromJSON(needs.setup.outputs.required-migrations)}}

env:
MANAGEMENT_TOKEN: ${{ secrets.CONTENTFUL_MANAGEMENT_TOKEN }}
SPACE_ID: ${{ secrets.TF_VAR_CPD_SPACE_ID }}

steps:
- uses: actions/checkout@v3

Expand Down Expand Up @@ -124,6 +138,9 @@ jobs:
runs-on: ubuntu-latest
env:
STAGING_ENVIRONMENT: ${{ needs.setup.outputs.staging-environment }}
MANAGEMENT_TOKEN: ${{ secrets.CONTENTFUL_MANAGEMENT_TOKEN }}
ENVIRONMENT: ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }}
SPACE_ID: ${{ secrets.TF_VAR_CPD_SPACE_ID }}

steps:
- uses: actions/checkout@v3
Expand All @@ -136,6 +153,6 @@ jobs:
working-directory: ./Contentful-Schema
run: npm ci

- name: Run script to point alias ${{ inputs.target_environment }} at new environment ${{ env.STAGING_ENVIRONMENT }}
- name: Run script to point alias ${{ inputs.target_environment == 'prod' && 'master' || inputs.target_environment }} at new environment ${{ env.STAGING_ENVIRONMENT }}
working-directory: ./Contentful-Schema/utils
run: node point-alias-at-environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ public class EntityResolverTests
[Test]
[TestCase("accordion", typeof(Accordion))]
[TestCase("accordionSection", typeof(AccordionSection))]
[TestCase("areaOfPractice", typeof(AreaOfPractice))]
[TestCase("areaOfPracticeList", typeof(AreaOfPracticeList))]
[TestCase("applicationFeature", typeof(ApplicationFeature))]
[TestCase("applicationFeatures", typeof(ApplicationFeatures))]
[TestCase("areaOfPractice", typeof(AreaOfPractice))]
[TestCase("areaOfPracticeList", typeof(AreaOfPracticeList))]
[TestCase("assetDownload", typeof(AssetDownload))]
[TestCase("audioResource", typeof(AudioResource))]
[TestCase("backToTop", typeof(BackToTop))]
[TestCase("columnLayout", typeof(ColumnLayout))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public partial class PartialsFactoryTests
new object[] { new AccordionSection(), "_AccordionSection" },
new object[] { new AreaOfPractice(), "_AreaOfPractice" },
new object[] { new AreaOfPracticeList(), "_AreaOfPracticeList" },
new object[] { new AssetDownload(), "_AssetDownload" },
new object[] { new AudioResource(), "_AudioResource" },
new object[] { new BackToTop(), "_BackToTop" },
new object[] { new ColumnLayout(), "_ColumnLayout" },
Expand Down
5 changes: 3 additions & 2 deletions Childrens-Social-Care-CPD/Contentful/EntityResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ public Type Resolve(string contentTypeId)
{
"accordion" => typeof(Accordion),
"accordionSection" => typeof(AccordionSection),
"areaOfPractice" => typeof(AreaOfPractice),
"areaOfPracticeList" => typeof(AreaOfPracticeList),
"applicationFeature" => typeof(ApplicationFeature),
"applicationFeatures" => typeof(ApplicationFeatures),
"areaOfPractice" => typeof(AreaOfPractice),
"areaOfPracticeList" => typeof(AreaOfPracticeList),
"assetDownload" => typeof(AssetDownload),
"audioResource" => typeof(AudioResource),
"backToTop" => typeof(BackToTop),
"columnLayout" => typeof(ColumnLayout),
Expand Down
9 changes: 9 additions & 0 deletions Childrens-Social-Care-CPD/Contentful/Models/AssetDownload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Contentful.Core.Models;

namespace Childrens_Social_Care_CPD.Contentful.Models;

public class AssetDownload : IContent
{
public string LinkText { get; set; }
public Asset Asset { get; set; }
}
1 change: 1 addition & 0 deletions Childrens-Social-Care-CPD/Contentful/PartialsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static string GetPartialFor(IContent item)
AccordionSection => "_AccordionSection",
AreaOfPractice => "_AreaOfPractice",
AreaOfPracticeList => "_AreaOfPracticeList",
AssetDownload => "_AssetDownload",
AudioResource => "_AudioResource",
BackToTop => "_BackToTop",
ColumnLayout => "_ColumnLayout",
Expand Down
155 changes: 155 additions & 0 deletions Childrens-Social-Care-CPD/Views/Shared/_AssetDownload.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
@using Childrens_Social_Care_CPD.Contentful.Models;
@using System.Collections.Generic;
@using System.Text.RegularExpressions

@model AssetDownload

@functions {

private string FileSizeToHumanReadable (long filesize)
{
long B = 0, KB = 1024, MB = KB * 1024, GB = MB * 1024, TB = GB * 1024;
double size = filesize;
string suffix = nameof(B);

if (filesize >= TB)
{
size = ConvertFileSize(filesize, TB);
suffix = nameof(TB);
}
else if (filesize >= GB)
{
size = ConvertFileSize(filesize, GB);
suffix = nameof(GB);
}
else if (filesize >= MB)
{
size = ConvertFileSize(filesize, MB);
suffix = nameof(MB);
}
else if (filesize >= KB)
{
size = ConvertFileSize(filesize, KB);
suffix = nameof(KB);
}

return $"{size} {suffix}";
}

private double ConvertFileSize(long filesize, long magnitude)
{
return Math.Round((double)filesize / magnitude, 2);
}

private string FileTypeToHumanReadable (string fileName, string contentType) {

var excelFileTypeString = "MS Excel Spreadsheet";
var wordFileTypeString = "MS Word Document";
var pdfFileTypeString = "<abbr title=\"Portable Document Format\" class=\"gem-c-attachment__abbr\">PDF</abbr>";
var odsFileTypeString = "ODS";

if (FileIsExcel(fileName, contentType)) return excelFileTypeString;
if (FileIsWord(fileName, contentType)) return wordFileTypeString;
if (FileIsODS(fileName, contentType)) return odsFileTypeString;
if (contentType == "application/pdf") return pdfFileTypeString;
return "Unknown file type";
}

private string FileTypeIconSVG (string fileName, string contentType)
{
var excelSVGMarkup = @"<svg class=""gem-c-attachment__thumbnail-image gem-c-attachment__thumbnail-image--spreadsheet"" version=""1.1"" viewBox=""0 0 99 140"" width=""99"" height=""140"" aria-hidden=""true"">
<path d=""M12 12h75v27H12zm0 47h18.75v63H12zm55 2v59H51V61h16m2-2H49v63h20V59z"" stroke-width=""0""></path>
<path d=""M49 61.05V120H32.8V61.05H49m2-2H30.75v63H51V59zm34 2V120H69.05V61.05H85m2-2H67v63h20V59z"" stroke-width=""0""></path>
<path d=""M30 68.5h56.5M30 77.34h56.5M30 112.7h56.5M30 95.02h56.5M30 86.18h56.5M30 103.86h56.5"" fill=""none"" stroke-miterlimit=""10"" stroke-width=""2""></path>
</svg>";

var wordSVGMarkup = @"<svg class=""gem-c-attachment__thumbnail-image gem-c-attachment__thumbnail-image--document"" version=""1.1"" viewBox=""0 0 99 140"" width=""99"" height=""140"" aria-hidden=""true"">
<path d=""M12 12h75v27H12zM12 59h9v9h-9zM12 77h9v9h-9zM12 95h9v9h-9zM12 113h9v9h-9zM30 59h57v9H30zM30 77h39v9H30zM30 95h57v9H30zM30 113h48v9H30z"" stroke-width=""0""></path>
</svg>";

var pdfSVGMarkup = @"<svg class=""gem-c-attachment__thumbnail-image gem-c-attachment__thumbnail-image--pdf"" version=""1.1"" viewBox=""0 0 99 140"">
<path d=""M12,59h9v9h-9v-9ZM30,77v9h39v-9H30ZM30,104h57v-9H30v9ZM30,122h48v-9H30v9ZM12,86h9v-9h-9v9ZM12,122h9v-9h-9v9ZM12,104h9v-9h-9v9ZM30,68h57v-9H30v9ZM35.2,21c-.3-.2-.6-.4-1-.5s-.8-.2-1.3-.2h-2.6v5.5h2.6c.5,0,1,0,1.3-.2s.7-.3,1-.5c.3-.2.5-.5.7-.8s.2-.7.2-1.1h0c0-.5,0-.9-.2-1.2-.2-.3-.4-.6-.7-.8h0ZM52.4,21.9c-.4-.5-1-.9-1.6-1.1-.7-.3-1.5-.4-2.4-.4h-2.7v11.5h2.7c.9,0,1.7-.1,2.4-.4s1.2-.7,1.6-1.1c.4-.5.7-1.1.9-1.7.2-.7.3-1.4.3-2.1v-.7c0-.8,0-1.5-.3-2.1-.2-.6-.5-1.2-.9-1.7h0ZM87,12v27H12V12h75ZM39.8,23c0-.9-.1-1.6-.4-2.4-.3-.7-.7-1.4-1.2-1.9-.5-.5-1.2-1-1.9-1.2-.8-.3-1.6-.5-2.5-.5h-7.2v17.9h3.6v-6h3.2c.9,0,1.8-.1,2.6-.5.8-.3,1.4-.7,2-1.2.5-.5,1-1.2,1.3-1.9.3-.7.5-1.5.5-2.4h0ZM57.4,26c0-1.3-.2-2.6-.5-3.7s-.9-2-1.6-2.8c-.7-.8-1.6-1.4-2.7-1.8-1.1-.4-2.3-.6-3.8-.6h-6.6v17.9h6.6c1.5,0,2.7-.2,3.8-.6,1.1-.4,2-1,2.7-1.8.7-.8,1.3-1.7,1.6-2.8.4-1.1.5-2.3.5-3.7h0ZM72.4,17.1h-12.1v17.9h3.6v-7.5h7.8v-3.3h-7.8v-3.8h8.4s0-3.3,0-3.3Z""></path>
</svg>";

if (FileIsExcel(fileName, contentType) || FileIsODS(fileName, contentType)) return excelSVGMarkup;
if (FileIsWord(fileName, contentType)) return wordSVGMarkup;
if (contentType == "application/pdf") return pdfSVGMarkup;
return "";
}
private bool FileIsExcel (string fileName, string contentType) {
var excelContentTypes = new List<string> {
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
};

if (excelContentTypes.Contains(contentType)) return true;

return MatchFileExtension(new List<string>{"xls", "xlsx"}, fileName);
}

private bool FileIsODS (string fileName, string contentType) {
var excelContentTypes = new List<string> {
"application/vnd.oasis.opendocument.spreadsheet"
};

if (excelContentTypes.Contains(contentType)) return true;

return MatchFileExtension(new List<string>{"ods"}, fileName);
}

private bool FileIsWord (string fileName, string contentType) {
var wordContentTypes = new List<string> {
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
};

if (wordContentTypes.Contains(contentType)) return true;

return MatchFileExtension(new List<string>{"doc", "docx"}, fileName);
}

private bool MatchFileExtension (List<string> extensions, string fileName) {
bool match = false;
extensions.ForEach(extension => {
if (Regex.IsMatch(fileName,@"\." + extension + "$", RegexOptions.None, TimeSpan.FromMilliseconds(100))) match = true;
});
return match;
}
}

@{
bool fileIsOds = FileIsODS(Model.Asset.File.FileName, Model.Asset.File.ContentType);
}

<section class="gem-c-attachment govuk-!-margin-bottom-6" data-module="ga4-link-tracker" data-ga4-link-tracker-module-started="true">
<div class="gem-c-attachment__thumbnail govuk-!-display-none-print">
<a class="govuk-link" target="_self" tabindex="-1" aria-hidden="true" data-ga4-link="{&quot;event_name&quot;:&quot;file_download&quot;,&quot;type&quot;:&quot;attachment&quot;}" href="@Model.Asset.File.Url">
@Html.Raw(@FileTypeIconSVG(@Model.Asset.File.FileName, @Model.Asset.File.ContentType))
</a>
</div>
<div class="gem-c-attachment__details">
<h3 class="gem-c-attachment__title">
<a class="govuk-link gem-c-attachment__link" target="_self" data-ga4-link="{&quot;event_name&quot;:&quot;file_download&quot;,&quot;type&quot;:&quot;attachment&quot;}" href="@Model.Asset.File.Url">
@Model.LinkText
</a>
</h3>
<p class="gem-c-attachment__metadata">
<span class="gem-c-attachment__attribute">@Html.Raw(@FileTypeToHumanReadable(@Model.Asset.File.FileName, @Model.Asset.File.ContentType))</span>, <span class="gem-c-attachment__attribute">@FileSizeToHumanReadable(@Model.Asset.File.Details.Size)</span>
</p>

@if (fileIsOds)
{
<p class="gem-c-attachment__metadata">
This file is in an <a href="https://www.gov.uk/guidance/using-open-document-formats-odf-in-your-organisation" target="_blank" rel="noopener" class="govuk-link">OpenDocument</a> format
</p>
}

<p class="gem-c-attachment__metadata">This file may not be suitable for users of assistive technology.</p>
<details data-module="ga4-event-tracker" data-ga4-event="{&quot;event_name&quot;:&quot;select_content&quot;,&quot;type&quot;:&quot;detail&quot;,&quot;text&quot;:&quot;Request an accessible format.&quot;,&quot;section&quot;:&quot;Request an accessible format.&quot;,&quot;index_section&quot;:1,&quot;index_section_count&quot;:1}" class="gem-c-details govuk-details govuk-!-margin-bottom-3" data-ga4-event-tracker-module-started="true">
<summary class="govuk-details__summary">
<span class="govuk-details__summary-text" data-ga4-expandable="">Request an accessible format</span>
</summary>
<div class="govuk-details__text">
If you use assistive technology (such as a screen reader) and need a version of this document in a more accessible format, please email <a href="mailto:develop-child-family-social-work-career-team@digital.education.gov.uk" target="_blank" class="govuk-link">develop-child-family-social-work-career-team@digital.education.gov.uk</a>. Please tell us what format you need. It will help us if you say what assistive technology you use.
</div>
</details>
</div>
</section>
Loading

0 comments on commit 4305713

Please sign in to comment.