Skip to content

Commit

Permalink
Merge pull request #350 from adobecom/cmc-api-connection
Browse files Browse the repository at this point in the history
[Cloud Console] Connect to API
  • Loading branch information
rayyank10 authored Jan 29, 2025
2 parents 763929e + 7e88552 commit 3c10d39
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 52 deletions.
82 changes: 62 additions & 20 deletions ecc/blocks/cmc/cmc.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
import { LIBS } from '../../scripts/scripts.js';
import { getCaasTags } from '../../scripts/esp-controller.js';
import { generateToolTip, readBlockConfig } from '../../scripts/utils.js';
import { getCaasTags, getClouds } from '../../scripts/esp-controller.js';
import { buildNoAccessScreen, generateToolTip, getDevToken, getEventServiceEnv, readBlockConfig, signIn } from '../../scripts/utils.js';
import CloudManagementConsole from '../../components/cmc/cmc.js';
import { initProfileLogicTree } from '../../scripts/profile.js';

const { createTag } = await import(`${LIBS}/utils/utils.js`);

export default async function init(el) {
generateToolTip(el);
function deepGetTagByTagID(tags, tagID) {
const tagIDs = tagID.replace('caas:', '').split('/');
let currentTag = tags;

const blockConfig = readBlockConfig(el);
tagIDs.forEach((tag) => {
currentTag = currentTag.tags[tag];
});

el.innerHTML = '';
return currentTag;
}

function buildLoadingScreen(el) {
el.classList.add('loading');
const loadingScreen = createTag('sp-theme', { color: 'light', scale: 'medium', class: 'loading-screen' });
createTag('sp-progress-circle', { size: 'l', indeterminate: true }, '', { parent: loadingScreen });
createTag('sp-field-label', {}, 'Loading Adobe Events Cloud Management Console...', { parent: loadingScreen });

el.prepend(loadingScreen);
}

async function buildCMC(el, blockConfig) {
await Promise.all([
import(`${LIBS}/deps/lit-all.min.js`),
import(`${LIBS}/features/spectrum-web-components/dist/theme.js`),
Expand All @@ -31,24 +46,51 @@ export default async function init(el) {

if (!caasTags) return;

// TODO: remove this mock data after cloud management console is fully integrated
const mockSavedTags = {
DX: [
'caas:events/session-type',
],
CreativeCloud: [
'caas:events/session-type/creativity-workshop',
],
DocumentCloud: [
'caas:events/session-type/creativity-workshop',
'caas:events/max/primary-poi',
],
};
const clouds = await getClouds();

const savedTags = {};
clouds.forEach((cloud) => {
const { cloudType, cloudTags } = cloud;

if (!cloudTags) return;

const fullTags = cloudTags.map((tag) => deepGetTagByTagID(caasTags, tag.caasId));

savedTags[cloudType] = fullTags || [];
});

customElements.define('cloud-management-console', CloudManagementConsole);

const tagManager = createTag('cloud-management-console', { class: 'cloud-management-console' }, '', { parent: el });
tagManager.tags = caasTags.namespaces.caas;
tagManager.savedTags = mockSavedTags;
tagManager.savedTags = savedTags;
tagManager.config = blockConfig;
tagManager.clouds = clouds;
}

export default async function init(el) {
generateToolTip(el);

const blockConfig = readBlockConfig(el);

el.innerHTML = '';
buildLoadingScreen(el);

const devToken = getDevToken();
if (devToken && ['local', 'dev'].includes(getEventServiceEnv())) {
buildCMC(el, blockConfig);
return;
}

await initProfileLogicTree('cmc', {
noProfile: () => {
signIn();
},
noAccessProfile: () => {
buildNoAccessScreen(el);
},
validProfile: () => {
buildCMC(el, blockConfig);
},
});
}
13 changes: 8 additions & 5 deletions ecc/blocks/event-format-component/event-format-component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable max-len */
import { SUPPORTED_CLOUDS } from '../../constants/constants.js';
import { getClouds } from '../../scripts/esp-controller.js';
import { LIBS } from '../../scripts/scripts.js';
import { generateToolTip } from '../../scripts/utils.js';

Expand All @@ -14,11 +14,14 @@ async function decorateCloudTagSelect(column) {
buSelectWrapper.append(select);
column.append(buSelectWrapper);

// FIXME: cloulds shouldn't be hardcoded
// const clouds = await getClouds();
const clouds = await getClouds();

Object.entries(SUPPORTED_CLOUDS).forEach(([, val]) => {
const opt = createTag('sp-menu-item', { value: val.id }, val.name);
Object.entries(clouds).forEach((cloud) => {
const { cloudType, cloudName } = cloud;

if (!cloudType || !cloudName) return;

const opt = createTag('sp-menu-item', { value: cloudType }, cloudName);
select.append(opt);
});

Expand Down
44 changes: 30 additions & 14 deletions ecc/components/cmc/cmc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { LIBS } from '../../scripts/scripts.js';
import style from './cmc.css.js';
import { getIcon } from '../../scripts/utils.js';
import { getCloud, updateCloud } from '../../scripts/esp-controller.js';

const { LitElement, html, repeat, nothing } = await import(`${LIBS}/deps/lit-all.min.js`);

Expand All @@ -13,6 +14,7 @@ export default class CloudManagementConsole extends LitElement {
static styles = style;

static properties = {
clouds: { type: Array },
currentCloud: { type: String },
tags: { type: Object },
currentPath: { type: String },
Expand Down Expand Up @@ -168,21 +170,34 @@ export default class CloudManagementConsole extends LitElement {

this.currentCloud = cloudType;
this.currentPath = startingPath;
this.selectedTags = new Set(savedCloudTags.map((tag) => this.deepGetTagByTagID(tag)));
this.selectedTags = new Set(savedCloudTags.map((tag) => this.deepGetTagByTagID(tag.tagID)));
this.pendingChanges = false;
this.requestUpdate();
}

save() {
this.savedTags[this.currentCloud] = this.getSelectedTags().map((tag) => tag.tagID);
async save() {
this.savedTags[this.currentCloud] = this.getSelectedTags();
this.pendingChanges = false;

this.toastState = {
open: true,
variant: 'positive',
text: 'Changes saved',
const cloudData = await getCloud(this.currentCloud);

// translate tagID to caasId, and title to name, and save to cloudData
const payload = {
cloudTags: this.getSelectedTags().map((tag) => ({
caasId: tag.tagID,
name: tag.title,
})),
};
// save to the server

const newCloudData = await updateCloud(this.currentCloud, { ...cloudData, ...payload });

if (newCloudData && !newCloudData.error) {
this.toastState = {
open: true,
variant: 'positive',
text: 'Changes saved',
};
}
}

render() {
Expand All @@ -204,9 +219,9 @@ export default class CloudManagementConsole extends LitElement {
<div class="tag-manager">
<sp-picker class="cloud-type-picker" @change=${(e) => this.switchCloudType(e.target.value)} label="Selected a Cloud type">
<sp-menu>
<sp-menu-item value="CreativeCloud" ?active=${this.currentCloud === 'CreativeCloud'}>Creative Cloud</sp-menu-item>
<sp-menu-item value="DX" ?active=${this.currentCloud === 'DX'}>Experience Cloud</sp-menu-item>
<sp-menu-item value="DocumentCloud" ?active=${this.currentCloud === 'DocumentCloud'}>Document Cloud</sp-menu-item>
${repeat(this.clouds.values(), (cloud) => html`
<sp-menu-item value="${cloud.cloudType}" ?active=${this.currentCloud === cloud.cloudType}>${cloud.cloudName}</sp-menu-item>
`)}
</sp-menu>
</sp-picker>
Expand Down Expand Up @@ -237,6 +252,7 @@ export default class CloudManagementConsole extends LitElement {
return nothing;
})}
</div>
${this.currentCloud ? html`
<div class="menu-group">
${this.currentPath.split('/').map((_p, i, arr) => {
const tag = this.deepGetTagByPath(arr, i);
Expand All @@ -251,16 +267,16 @@ export default class CloudManagementConsole extends LitElement {
return nothing;
})}
</div>
</div>` : nothing}
</div>
</div>
<div class="action-bar">
<sp-toast ?open=${this.toastState.open} variant=${this.toastState.variant} size="m" timeout="6000">${this.toastState.text}</sp-toast>
<sp-button variant="secondary" size="l" ?disabled=${!this.pendingChanges} @click=${() => {
<sp-button variant="secondary" size="l" ?disabled=${!this.pendingChanges || !this.currentCloud} @click=${() => {
const fullSavedTags = this.savedTags[this.currentCloud]?.map((tag) => this.deepGetTagByTagID(tag)) || [];
this.selectedTags = new Set(fullSavedTags); this.pendingChanges = false;
}}>Cancel</sp-button>
<sp-button variant="primary" size="l" ?disabled=${!this.pendingChanges} @click=${this.save}>Save</sp-button>
<sp-button variant="primary" size="l" ?disabled=${!this.pendingChanges || !this.currentCloud} @click=${this.save}>Save</sp-button>
</div>
`;
}
Expand Down
86 changes: 73 additions & 13 deletions ecc/scripts/esp-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ export const getCaasTags = (() => {
})();

export function waitForAdobeIMS() {
if (getDevToken()) return Promise.resolve();
if (getEventServiceEnv() === 'local') {
if (getDevToken()) {
return Promise.resolve();
}
return Promise.reject(new Error('Missing authentication token'));
}

return new Promise((resolve) => {
const checkIMS = () => {
Expand Down Expand Up @@ -365,6 +370,73 @@ export async function replaceVenue(eventId, venueId, venueData) {
}
}

export async function getClouds() {
const { host } = API_CONFIG.esp[getEventServiceEnv()];
const options = await constructRequestOptions('GET');

try {
const response = await safeFetch(`${host}/v1/clouds`, options);
const data = await response.json();

if (!response.ok) {
window.lana?.log('Failed to get clouds. Status:', response.status, 'Error:', data);
return { status: response.status, error: data };
}

return data.clouds;
} catch (error) {
window.lana?.log('Failed to get clouds. Error:', error);
return { status: 'Network Error', error: error.message };
}
}

export async function getCloud(cloudType) {
if (!cloudType || typeof cloudType !== 'string') throw new Error('Invalid cloud ID');

const { host } = API_CONFIG.esp[getEventServiceEnv()];
const options = await constructRequestOptions('GET');

try {
const response = await safeFetch(`${host}/v1/clouds/${cloudType}`, options);
const data = await response.json();

if (!response.ok) {
window.lana?.log('Failed to get cloud. Status:', response.status, 'Error:', data);
return { status: response.status, error: data };
}

return data;
} catch (error) {
window.lana?.log('Failed to get cloud. Error:', error);
return { status: 'Network Error', error: error.message };
}
}

export async function updateCloud(cloudType, cloudData) {
if (!cloudType || typeof cloudType !== 'string') throw new Error('Invalid cloud Type');
if (!cloudData || typeof cloudData !== 'object') throw new Error('Invalid cloud data');

const { host } = API_CONFIG.esp[getEventServiceEnv()];
const raw = JSON.stringify(cloudData);

const options = await constructRequestOptions('PUT', raw);

try {
const response = await safeFetch(`${host}/v1/clouds/${cloudType}`, options);
const data = await response.json();

if (!response.ok) {
window.lana?.log('Failed to update cloud. Status:', response.status, 'Error:', data);
return { status: response.status, error: data };
}

return data;
} catch (error) {
window.lana?.log('Failed to update cloud. Error:', error);
return { status: 'Network Error', error: error.message };
}
}

export async function createEvent(payload) {
if (!payload || typeof payload !== 'object') throw new Error('Invalid event payload');

Expand Down Expand Up @@ -949,18 +1021,6 @@ export async function getVenue(eventId) {
}
}

export async function getClouds() {
// TODO: use ESP to fetch clouds rather than Chimera
const tags = await getCaasTags();

if (tags) {
const clouds = tags.namespaces.caas.tags['business-unit'].tags;
return clouds;
}

return null;
}

export async function getAllSeries() {
const { host } = API_CONFIG.esp[getEventServiceEnv()];
const options = await constructRequestOptions('GET');
Expand Down

0 comments on commit 3c10d39

Please sign in to comment.