Skip to content

Commit

Permalink
LTLC-115969 Update UI extension, add greeting controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Octavian Condre committed Sep 5, 2024
1 parent bb91961 commit 7c3af17
Show file tree
Hide file tree
Showing 26 changed files with 482 additions and 3,763 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;

namespace Rws.LC.UISampleApp.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class GreetingController : ControllerBase
{
/// <summary>
/// The logger.
/// </summary>
private ILogger<GreetingController> logger;

public GreetingController(ILogger<GreetingController> logger)
{
this.logger = logger;
}

/// <summary>
/// This endpoint always returns "Hello world!".
/// </summary>
/// <returns>The hardcoded greeting message.</returns>
[Authorize]
[HttpGet("")]
public ActionResult GetGreeting()
{
logger.LogInformation("Retrieving greeting.");
return Ok(new JsonObject() { { "greeting", "Hello, world!" } });
}
}
}

This file was deleted.

This file was deleted.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { trados, ExtensibilityEventDetail, Project, tradosProjectTemplateApi } from "@trados/trados-ui-extensibility";
import { logExtensionData } from "./helpers";

/**
* Handles the callAppApiButton's click event.
* Calls my own app's greeting API to receive the greeting message which is included in a notification.
*
* @param detail The event detail object.
*/
export const callAppApiButtonClicked = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);

trados
// The callAppApi function will automatically add headers: the account identifier and authorization token.
.callAppApi({
url: `api/greeting/`,
method: "GET"
})
.then(data => {
trados.showNotification(
`App backend says <b>${data?.responseData?.greeting}</b>`,
trados.contexts.projects,
trados.notificationTypes.success
);
})
.catch(reason => {
console.error("[UI Extensibility] [my UI extension] Failed to call my app's API", reason);
trados.showNotification(
"Failed to call my app's API.",
trados.contexts.projects,
trados.notificationTypes.fail
);
});
}

/**
* Handles the callPublicApiButton's render event.
* Checks whether the current project is based on a project template, then updates callPublicApiButton's hidden property depending on the outcome.
*
* @param detail The event detail object.
*/
export const callPublicApiButtonRendered = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);
const hidden = !detail.project?.projectTemplate;
trados.updateElement("callPublicApiButton", { hidden: hidden });
};

/**
* Handles the callPublicApiButton's click event.
* Calls the ProjectTemplateAPI from Language Cloud Public API to get the current project's project template and displays its name in a notification.
*
* @param detail The event detail object.
*/
export const callPublicApiButtonClicked = (detail: ExtensibilityEventDetail) => {
logExtensionData(detail);

const projectTemplateId = detail.project?.projectTemplate?.id;
if (projectTemplateId) {
// Call the function that initializes the tradosProjectTemplateApi.
tradosProjectTemplateApi()
// Call the getProjectTemplate API endpoint.
.getProjectTemplate({
// Provide the project template identifier.
projectTemplateId: projectTemplateId,
// Provide the account identifier and authorization token returned by the getRegistrationResult function.
...trados.getRegistrationResult()
})
.then(apiData => {
console.log("[UI Extensibility] [my UI extension] Project template details from Language Cloud Public API", apiData);

trados.showNotification(
`This project was created using the <b>${apiData.name}</b> project template`,
trados.contexts.projects,
trados.notificationTypes.success
);
})
.catch(e => {
console.error(`[UI Extensibility] [my UI extension] API call failed`, e );
});
}
}

/**
* Handles the myNavigateButton's render event.
* Checks whether the current project is based on a project template, then updates myNavigateButton's hidden property depending on the outcome.
*
* @param detail The event detail object.
*/
export const myNavigateButtonRendered = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);
const hidden = !detail.project?.projectTemplate;
trados.updateElement("myNavigateButton", { hidden: hidden });
};

/**
* Handles the myNavigateButton's click event.
* Navigates to the current project's project template details view.
*
* @param detail The event detail object.
*/
export const myNavigateButtonClicked = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);
if (detail.project?.projectTemplate) {
const projectTemplateId = detail.project.projectTemplate.id;
const projectTemplatePath = `resources/project-templates/${projectTemplateId}`;
trados.navigate(projectTemplatePath, trados.navigationTypes.route);
}
};

/**
* Handles the myGetUiDataButton's click event.
* Gets the currently active tab in the project details view from the event detail; the onclick action's payload is ["projectActiveTab"].
* Gets the currently selected projects in the projects list view using the getLocalData function as an alternative to the action payload approach.
* Shows a notification containing both the active tab and the selected projects in the projects list.
*
* @param detail The event detail object.
*/
export const myGetUiDataButtonClicked = (detail: ExtensibilityEventDetail) => {
logExtensionData(detail);

// The click event detail contains local data requested via onclick action's payload - see extension elements array in index.ts.
const myActiveTab = detail.projectActiveTab;

// You can also request local UI data using the trados.getLocalData function.
trados
.getLocalData(trados.contexts.projects, trados.dataSelectors.selectedProjects)
.then((data: { selectedProjects: Project[] }) => {
const mySelectedProjects = data.selectedProjects;
const mySelectedProjectsCount = mySelectedProjects.length;
const notificationData = [
`My active tab is <b>${myActiveTab}</b>.`,
mySelectedProjectsCount
? `My selected projects (${mySelectedProjectsCount}):<br>${mySelectedProjects.map(p => " - " + p.name).join("<br>")}`
: "No selected projects"
];
trados.showNotification(notificationData.join("<br><br>"), trados.contexts.projects)
})
.catch(reason => {
console.error("[UI Extensibility] [my UI extension] Failed to get local data", reason);
trados.showNotification(
"Failed to get local data.",
trados.contexts.projects,
trados.notificationTypes.fail
);
});
};
Original file line number Diff line number Diff line change
@@ -1,84 +1,10 @@
import { ExtensibilityEventDetail } from "@sdl/extensibility-types/extensibility";
import {
currentProject,
projectImportanceList
} from "./projectToolbarHandlers";
import { ExtensibilityEventDetail } from "@trados/trados-ui-extensibility";

/**
* Logs the event detail object to the console.
*
* @param detail The event detail object.
*/
export const logExtensionData = (detail: ExtensibilityEventDetail) => {
console.log("[UI Extensibility] [extension] Custom event detail", detail);
console.log("[UI Extensibility] [my UI extension] Custom event detail", detail);
};

// simple file download
// no longer used for initial "Create invoice" button; still used for "Get local data" button
export const download = (filename: string, data: string | Blob) => {
const element = document.createElement("a");
if (typeof data === "string") {
element.href = "data:text/plain;charset=utf-8," + encodeURIComponent(data);
} else {
element.href = URL.createObjectURL(data);
}
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
};

export const downloadData = (data: any) => {
const filename = "local-data.txt";
console.log(
`[UI Extensibility] [extension] Download data as ${filename} file`,
data
);

setTimeout(() => {
download(filename, JSON.stringify(data));
}, 1);
};

export const updateProjectImportanceList = (data?: any) => {
const currentProjectImportanceItem = projectImportanceList.find(
i => i.projectId === currentProject!.id
);
if (currentProjectImportanceItem) {
if (data.responseData.importance) {
// update existing entry
currentProjectImportanceItem.importance =
data.responseData.importance.toLowerCase();
if (currentProjectImportanceItem.pending) {
currentProjectImportanceItem.pending = false;
currentProjectImportanceItem.id = data.responseData.id;
}
} else {
// delete entry
projectImportanceList.splice(
projectImportanceList.indexOf(currentProjectImportanceItem),
1
);
}
} else {
// add entry
projectImportanceList.push({
id: data.responseData.id,
projectId: data.responseData.projectId,
importance: data.responseData.importance,
pending: false
});
}
};

// a similar function exists in public-packages/extensibility/src/api/apiClient.ts but is intentionally not exported
// this helper function in the mock extension is used when calling add-on/app backend api directly, see api/project-metadata in projects-app/src/mocks/ui-extensibility/extensions/handlers/projectToolbarHandlers.ts
export const getEnvironmentUrlPartByHost = () => {
const hostEnv = document.location.host.split("-")[0];
switch (hostEnv) {
case "ci":
case "qa":
case "pte":
case "uat":
case "staging":
return `${hostEnv}-`;
default:
return ""; // prod
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ExtensibilityEventDetail } from "@trados/trados-ui-extensibility";
import { logExtensionData } from "./helpers";

/**
* Handles myCustomSidebarBox's render event.
* Adds HTML content to the sidebarBox.
*
* @param detail The event detail object.
*/
export const myCustomSidebarBoxRendered = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);

const sidebarBoxContentWrapper = document.getElementById(detail.domElementId);
if (sidebarBoxContentWrapper) {
// Reset content for re-renders: as the state changes in the Trados UI depending on user actions, re-renders occur.
sidebarBoxContentWrapper.innerHTML = "";

// Create and append div.
const div = document.createElement("div");
div.innerHTML = `Custom sidebar box content inserted on render.`;
sidebarBoxContentWrapper.appendChild(div);
}
};

/**
* Handles myCustomPanel's render event.
* Adds HTML content to the panel.
*
* @param detail The event detail object.
*/
export const myCustomPanelRendered = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);

const panelContentWrapper = document.getElementById(detail.domElementId);
if (panelContentWrapper) {
// Reset content for re-renders: as the state changes in the Trados UI depending on user actions, re-renders occur.
panelContentWrapper.innerHTML = "";

// Create and append div.
const div = document.createElement("div");
div.innerHTML = `Custom panel content inserted on render.`;
panelContentWrapper.appendChild(div);
}
};

/**
* Handles myCustomTab's render event.
* Adds HTML content to the tab.
*
* @param detail The event detail object.
*/
export const myCustomTabRendered = (
detail: ExtensibilityEventDetail
) => {
logExtensionData(detail);

const tabContentWrapper = document.getElementById(detail.domElementId);
if (tabContentWrapper) {
// Reset content for re-renders: as the state changes in the Trados UI depending on user actions, re-renders occur.
tabContentWrapper.innerHTML = "";

// Create and append div.
const div = document.createElement("div");
div.innerHTML = `Custom tab content inserted on render.`;
tabContentWrapper.appendChild(div);
}
};
Loading

0 comments on commit 7c3af17

Please sign in to comment.