Skip to content
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
8 changes: 5 additions & 3 deletions examples/Demo/Client/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using FluentUI.Demo.Shared;
using FluentUI.Demo.Shared.SampleData;

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.FluentUI.AspNetCore.Components;
Expand All @@ -13,6 +17,4 @@
builder.Services.AddFluentUIComponents();
builder.Services.AddFluentUIDemoClientServices();

builder.Services.AddScoped<DataSource>();

await builder.Build().RunAsync();
17 changes: 0 additions & 17 deletions examples/Demo/Client/wwwroot/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,6 @@
<link href="_content/FluentUI.Demo.Shared/css/site.css" rel="stylesheet" />
<link href="FluentUI.Demo.Client.styles.css" rel="stylesheet" />
<link href="_content/FluentUI.Demo.Shared/css/site.css" rel="stylesheet" />

<!-- Statistics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-VML6BZWWTC"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());

gtag('config', 'G-VML6BZWWTC');
</script>
<script type="text/javascript">
(function(c, l, a, r, i, t, y) {
c[a] = c[a] || function() { (c[a].q = c[a].q || []).push(arguments) };
t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i;
y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y);
})(window, document, "clarity", "script", "hnr14wvzj8");
</script>
</head>

<body>
Expand Down
2 changes: 1 addition & 1 deletion examples/Demo/Server/FluentUI.Demo.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<NoWarn>$(NoWarn);CS1591;CS1573</NoWarn>
</PropertyGroup>

<ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Shared\FluentUI.Demo.Shared.csproj" />
</ItemGroup>

Expand Down
4 changes: 4 additions & 0 deletions examples/Demo/Server/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using FluentUI.Demo.Shared;
using FluentUI.Demo.Shared.SampleData;
using Microsoft.AspNetCore.Hosting.StaticWebAssets;
Expand Down
20 changes: 20 additions & 0 deletions examples/Demo/Shared/Components/Cookies/CookieConsent.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@if (_showBanner)
{
<div id="cookieconsent" role="alert">
<div class="info">
<div class="infoicon">
<FluentIcon Value="@(new Microsoft.FluentUI.AspNetCore.Components.Icons.Regular.Size28.Info())" />
</div>
<p class="infomessage">
We use optional cookies to improve your experience on our websites, such as through social media connections, and to display personalized advertising based on your online activity. If you reject optional cookies, only cookies necessary to provide you the services will be used. You may change your selection by clicking “Manage Cookies”.
<a target="_blank" href="https://go.microsoft.com/fwlink/?LinkId=521839">Privacy Statement</a>
<a target="_blank" href="https://aka.ms/3rdpartycookies">Third-Party Cookies</a>
</p>
</div>
<div class="buttons">
<FluentButton Class="button" @onclick="AcceptPolicyAsync" Title="Accept" Appearance="Appearance.Outline">Accept</FluentButton>
<FluentButton Class="button" @onclick="RejectPolicyAsync" Title="Reject" Appearance="Appearance.Outline">Reject</FluentButton>
<FluentButton Class="button" @onclick="ManageCookiesAsync" Title="Manage cookies" Appearance="Appearance.Outline">Manage cookies</FluentButton>
</div>
</div>
}
90 changes: 90 additions & 0 deletions examples/Demo/Shared/Components/Cookies/CookieConsent.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using Microsoft.AspNetCore.Components;
using Microsoft.FluentUI.AspNetCore.Components;

namespace FluentUI.Demo.Shared.Components.Cookies;

public partial class CookieConsent()
{
private const string GA_MEASUREMENT_ID = "G-VML6BZWWTC"; // Google Analytics measurement ID
private const string MC_PROIOJECT_ID = "hnr14wvzj8"; // Microsoft Clarity project ID

[Inject]
public required CookieConsentService CookieConsentService { get; set; }

[Inject]
public IDialogService DialogService { get; set; } = default!;

private IDialogReference? _dialog;
private bool _showBanner = false;
private CookieState? _cookieState;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_cookieState ??= await CookieConsentService.GetCookieStateAsync();
_showBanner = _cookieState is null;

if (!_showBanner && _cookieState?.AcceptAnalytics == true)
{
await InitAnalyticsAsync();
}
StateHasChanged();
}
}

private async Task AcceptPolicyAsync()
{
_cookieState = new CookieState(true);
await CookieConsentService.SetCookieStateAsync(_cookieState);
await InitAnalyticsAsync();

_showBanner = false;
}

private async Task RejectPolicyAsync()
{
await CookieConsentService.SetCookieStateAsync(new CookieState(false));

_showBanner = false;
}

public async Task ManageCookiesAsync()
{
_cookieState ??= await CookieConsentService.GetCookieStateAsync() ?? new();

_dialog = await DialogService.ShowDialogAsync(DialogHelper.From<ManageCookies>(), _cookieState, new DialogParameters()
{
Title = $"Manage cookie preferences",
PrimaryAction = "Save changes",
SecondaryAction = "Reset all",
ShowDismiss = true,
Width = "640px",
Height = "610px",
PreventDismissOnOverlayClick = true,
PreventScroll = true,

});
var result = await _dialog.Result;

if (!result.Cancelled && result.Data is not null)
{
_cookieState = (CookieState)result.Data;

await CookieConsentService.SetCookieStateAsync(_cookieState);
await InitAnalyticsAsync();
}
}

private async Task InitAnalyticsAsync()
{
if (_cookieState?.AcceptAnalytics == true)
{
await CookieConsentService.InitAnalyticsAsync(GA_MEASUREMENT_ID, MC_PROIOJECT_ID);
}
}
}
43 changes: 43 additions & 0 deletions examples/Demo/Shared/Components/Cookies/CookieConsent.razor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#cookieconsent {
position: relative;
display: flex;
z-index: 998;
width: 100%;
justify-content: space-between;
text-align: left;
background-color: var(--neutral-layer-2);
}

.info {
margin: 0;
padding-left: 5%;
padding-top: 8px;
padding-bottom: 8px;
}
.infoicon {
display: table-cell;
padding: 12px;
width: 24px;
height: 24px;
}

.infomessage {
display: table-cell;
vertical-align: middle;
padding: 0;
}

.buttons {
display: inline-block;
margin-left: 5%;
margin-right: 5%;
min-width: 40%;
min-width: calc((150px + 3 * 4px) * 2 + 150px);
min-width: fit-content;
align-self: center;
position: relative;
}

.button {
min-width: 150px;
}
92 changes: 92 additions & 0 deletions examples/Demo/Shared/Components/Cookies/CookieConsent.razor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments) };

const injectGAScript = (measurementId) => {
// Load the Google tag manager script dynamically
const script = document.createElement('script');
script.async = true;
script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
document.head.appendChild(script);

// Initialize GA4 once the script loads
script.onload = () => {
gtag('js', new Date());
gtag('config', measurementId);
console.log('Google Analytics 4 initialized successfully');
};

script.onerror = () => {
console.error('Failed to load Google Analytics 4');
};
};
function injectMCScript(projectId) {
try {
(function (c, l, a, r, i, t, y) {
if (l.getElementById("clarity-script")) {
return;
}
c[a] = c[a] ||
function () {
(c[a].q = c[a].q || []).push(arguments);
};
t = l.createElement(r);
t.async = 1;
t.src = "https://www.clarity.ms/tag/" + i + "?ref=npm";
t.id = "clarity-script"
y = l.getElementsByTagName(r)[0];
y.parentNode.insertBefore(t, y);
})(window, document, "clarity", "script", projectId);
console.log('Microsoft Clarity initialized successfully');
return;
} catch (error) {
console.error('Failed to load Microsoft Clarity');
return;
}
};

const Clarity = {
init(projectId) {
injectMCScript(projectId, 'clarity-script');
},

setTag(key, value) {
window.clarity('set', key, value);
},

identify(customerId, customSessionId, customPageId, friendlyName) {
window.clarity('identify', customerId, customSessionId, customPageId, friendlyName);
},

consent(consent = true) {
window.clarity('consent', consent);
},

upgrade(reason) {
window.clarity('upgrade', reason);
},

event(eventName) {
window.clarity('event', eventName);
},
};

export async function getCookiePolicy() {
const cookiePolicy = localStorage.getItem("cookie-policy")

return JSON.parse(cookiePolicy)
}

export async function setCookiePolicy(state) {
localStorage.setItem("cookie-policy", JSON.stringify(state))
}

export async function initAnalytics(GAmeasurementId, MCprojectId) {
// Google Analytics initialization
injectGAScript(GAmeasurementId);

// Microsoft Clarity initialization
Clarity.init(MCprojectId)
Clarity.consent()

console.log("Analytics initialized")
}
42 changes: 42 additions & 0 deletions examples/Demo/Shared/Components/Cookies/CookieConsentService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using Microsoft.FluentUI.AspNetCore.Components.Utilities;
using Microsoft.JSInterop;

namespace FluentUI.Demo.Shared.Components.Cookies;

public class CookieConsentService(IJSRuntime jsRuntime) : JSModule(jsRuntime, "./_content/FluentUI.Demo.Shared/Components/Cookies/CookieConsent.razor.js")
{
private CookieState? _cookieState;

public async Task<bool> IsAnalyticsConsentedAsync() =>
(await GetCookieStateAsync())?.AcceptAnalytics == true;

public async Task<bool> IsSocialMediaConsentedAsync() =>
(await GetCookieStateAsync())?.AcceptSocialMedia == true;

public async Task<bool> IsAdvertisingConsentedAsync() =>
(await GetCookieStateAsync())?.AcceptAdvertising == true;

public async Task<bool> IsConsentGivenAsync() =>
await GetCookieStateAsync() != null;

public async Task<CookieState?> GetCookieStateAsync()
{
_cookieState ??= await InvokeAsync<CookieState>("getCookiePolicy");
return _cookieState;
}

public async Task SetCookieStateAsync(CookieState state)
{
await InvokeVoidAsync("setCookiePolicy", state);
}

public async Task InitAnalyticsAsync(string gaMeasurementID, string mcProjectID)
{
await InvokeVoidAsync("initAnalytics", gaMeasurementID, mcProjectID);
}

}
20 changes: 20 additions & 0 deletions examples/Demo/Shared/Components/Cookies/CookieState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

namespace FluentUI.Demo.Shared.Components.Cookies;

public class CookieState(bool? acceptAnalysis, bool? acceptSocialMedia, bool? acceptAdvertising)
{
public bool? AcceptAnalytics { get; set; } = acceptAnalysis;
public bool? AcceptSocialMedia { get; set; } = acceptSocialMedia;
public bool? AcceptAdvertising { get; set; } = acceptAdvertising;

public CookieState() : this(null, null, null)
{
}

public CookieState(bool acceptAll) : this(acceptAll, acceptAll, acceptAll)
{
}
}
Loading