Skip to content

Commit

Permalink
Merge pull request #8 from matterway/feat/navigate-and-create-entries
Browse files Browse the repository at this point in the history
Feat/navigate and create entries
  • Loading branch information
aladoui authored May 27, 2024
2 parents 6a24d8f + 9b8c6c0 commit 228fb5f
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 49 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@matterway/skill-scripts": "^10.0.6-stable",
"@matterway/types": "^10.0.3",
"@types/lodash-es": "^4.17.12",
"dayjs": "^1.11.11",
"exceljs": "^4.4.0",
"i18next": "^22.4.15",
"lodash-es": "^4.17.21",
Expand Down
6 changes: 5 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"proceedButton": "Let's go!"
},
"success": {
"subtitle": "Task processed successfully",
"subtitle": "Your task is complete!",
"text": "The request has been processed successfully. You can now dismiss Assistant and work on a new task.",
"successButton": "Thank you"
},
Expand All @@ -13,6 +13,10 @@
"text": "Assistant has encountered unexpected circumstances, and is unable to proceed. The following error message will help support investigate the issue: {{err}}",
"dismissButton": "Dismiss"
},
"progress": {
"fetchData": "Fetching data",
"createData": "Creating project entries"
},
"uploadFile": {
"title": "Upload project file",
"description": "Create entries for your favorite project 😉",
Expand Down
16 changes: 8 additions & 8 deletions src/manifest.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"manifest_version": 3,
"identifier": "@matterway/ytf",
"name": "My Skill",
"description": "Description of My Skill.",
"name_de": "New skill German name",
"description_de": "New skill German description",
"name_fr": "New skill French name",
"description_fr": "New skill French description",
"name_nl": "New skill Dutch name",
"description_nl": "New skill Dutch description",
"name": "Yeti Force Projects",
"description": "Create entries for your favorites projects",
"name_de": "Yeti Force Projects",
"description_de": "NCreate entries for your favorites projects",
"name_fr": "Yeti Force Projects",
"description_fr": "Create entries for your favorites projects",
"name_nl": "Yeti Force Projects",
"description_nl": "Create entries for your favorites projects",
"icon": "icon.png",
"background_script": "background.js",
"content_script": "content.js",
Expand Down
35 changes: 19 additions & 16 deletions src/shared/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
// Keep shared selectors here,
export const SELECTORS = {};

/**
* @example
*
* export const SELECTORS = {
* loader: {
* materialNumberLabel: '#userarea-scrl-cnt > div > div:first-child label span',
* materialNumberInput: 'input[title="Material Number"]',
* },
* xPurchDocTableCell: '//table//tr//span[text()="Purch.Doc."]',
* xCurrencyInput: '//span[contains(text(), "Targ. Val.")]//following::input[2]',
* xTranslatedSpan: (title: string) => `//span[contains(text(), ${title}`,
* };
*/
export const SELECTORS = {
navigateToProjectManagement: {
projects: 'span[title="Projects"]',
xAddRecordsBtn: '//a[contains(text(), "Add record")]',
},
createEntries: {
projectName: '[name="projectname"]',
startDate: '[name="startdate"]',
targetEndDate: '[name="targetenddate"]',
budget: '[name="targetbudget"]',
xSaveBtn: '//button//*[contains(text(), "Save")]',
xProjectsBreadcrumb:
'//li[@class="breadcrumb-item u-text-ellipsis"]//a[contains(text(), "Projects")]',
},
highlightCreatedEntries: {
xProjectName: (projectName: string) =>
`//table[contains(@class, 'listViewActive')]//a[contains(text(), "${projectName}")]`,
},
};
7 changes: 7 additions & 0 deletions src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ export interface SkillData {
// Example data
id: number;
}

export interface Entry {
projectName: string;
startDate?: string;
targetEndDate?: string;
budget?: string;
}
11 changes: 9 additions & 2 deletions src/steps/@start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ import {Context} from '@matterway/sdk';
import {successStep} from 'steps/@success';
import {uploadFileStep} from './uploadFile';
import {extractFileDataStep} from './extractFileData';
import {navigateToProjectManagementStep} from './navigateToProjectManagement';
import {createEntriesStep} from './createEntries';
import {highlightCreatedEntriesStep} from './highlightCreatedEntries';

export async function startStep(ctx: Context) {
console.log('step: startStep');

const uploadedFile = await uploadFileStep(ctx);

let highlights: string[] = [];
if (uploadedFile !== null) {
const _excelData = await extractFileDataStep(ctx, uploadedFile);
const excelData = await extractFileDataStep(ctx, uploadedFile);
await navigateToProjectManagementStep(ctx);
await createEntriesStep(ctx, excelData);
highlights = await highlightCreatedEntriesStep(ctx, excelData);
}

await successStep(ctx);
await successStep(ctx, highlights);
}
18 changes: 12 additions & 6 deletions src/steps/@success.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import type {Context} from '@matterway/sdk';
import {showSuccessNotice} from '@matterway/sdk';
import {highlightXPath, showSuccessNotice} from '@matterway/sdk';
import {t} from 'i18next';
import manifest from 'manifest.json';

// You can duplicate this step to represent different endings for this task
// which are not "technical errors", such as "could not find the material".

export async function successStep(ctx: Context) {
export async function successStep(ctx: Context, highlights: string[]) {
console.log('step: successStep');

// Only add logic here if it is performing closure specific to this ending

await showSuccessNotice(ctx, {
title: manifest.name,
description: manifest.description,
title: '',
description: '',
text: '',
subtitle: t('success.subtitle'),
text: t('success.text'),
icon: 'checkmark-circle-outline',
});

await Promise.all(
highlights.map((highlight) => {
return highlightXPath(ctx, highlight).stop();
}),
);
}
55 changes: 55 additions & 0 deletions src/steps/createEntries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
clickByXPath,
fill,
waitForSelector,
type Context,
setValue,
showProgress,
} from '@matterway/sdk';
import {SELECTORS} from 'shared/selectors';
import {Entry} from 'shared/types';
import dayjs from 'dayjs';
import {t} from 'i18next';
import {isEmpty} from 'lodash-es';

export async function createEntriesStep(ctx: Context, excelData: Entry[]) {
console.log('step: createEntriesStep', excelData);
await showProgress(ctx, t('progress.createData'));

const {
navigateToProjectManagement: {xAddRecordsBtn},
createEntries: {
projectName,
startDate,
targetEndDate,
budget,
xSaveBtn,
xProjectsBreadcrumb,
},
} = SELECTORS;

if (excelData.length > 0) {
for (const entry of excelData) {
if (isEmpty(entry.projectName)) {
continue;
}

const formattedDate = dayjs(entry.startDate).format('YYYY-MM-DD');
const formattedEndDate = dayjs(entry.targetEndDate).format('YYYY-MM-DD');

await clickByXPath(ctx, xAddRecordsBtn);
await showProgress(ctx, t('progress.createData'));
await waitForSelector(ctx, projectName);
await fill(ctx, projectName, entry.projectName);
await setValue(ctx, startDate, formattedDate);
await setValue(ctx, targetEndDate, formattedEndDate);
await fill(ctx, budget, String(entry.budget));
await clickByXPath(ctx, xSaveBtn);
await showProgress(ctx, t('progress.createData'));
await clickByXPath(ctx, xProjectsBreadcrumb);
await showProgress(ctx, t('progress.createData'));
}
}

console.log('step: createEntriesStep end');
}
34 changes: 19 additions & 15 deletions src/steps/extractFileData.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import {SDKFile, convertBase64ToBuffer, type Context} from '@matterway/sdk';
import {
SDKFile,
convertBase64ToBuffer,
showProgress,
type Context,
} from '@matterway/sdk';
import {Workbook} from 'exceljs';
import {t} from 'i18next';
import {isEmpty} from 'lodash-es';
import {Entry} from 'shared/types';

export async function extractFileDataStep(ctx: Context, excelFile: SDKFile) {
console.log('step: extractFileDataStep', {excelFile});

await showProgress(ctx, t('progress.fetchData'));

const fileBuffer = convertBase64ToBuffer(excelFile.data);
const workbook = await new Workbook().xlsx.load(fileBuffer);
const worksheet = workbook.worksheets[0];

const data = worksheet.getRows(2, worksheet.rowCount);
const extractedData = data
?.map((row) => ({
projectName: row.getCell(1).value,
startDate: row.getCell(2).value,
targetEndDate: row.getCell(3).value,
budget: row.getCell(4).value,
}))
.filter(
(obj) =>
!isEmpty(obj.projectName) ||
!isEmpty(obj.startDate) ||
!isEmpty(obj.targetEndDate) ||
!isEmpty(obj.budget),
);
const extractedData: Entry[] =
data
?.map((row) => ({
projectName: row.getCell(1).value?.toString() || '',
startDate: row.getCell(2).value?.toString() || '',
targetEndDate: row.getCell(3).value?.toString() || '',
budget: row.getCell(4).value?.toString() || '',
}))
.filter((obj) => !isEmpty(obj.projectName)) || [];

console.log('step: extractFileDataStep end', {extractedData});
return extractedData;
Expand Down
45 changes: 45 additions & 0 deletions src/steps/highlightCreatedEntries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {highlightXPath, type Context} from '@matterway/sdk';
import {isEmpty} from 'lodash-es';
import {SELECTORS} from 'shared/selectors';
import {Entry} from 'shared/types';

export async function highlightCreatedEntriesStep(
ctx: Context,
excelData: Entry[],
) {
console.log('step: highlightCreatedEntriesStep', {excelData});
const {
highlightCreatedEntries: {xProjectName},
} = SELECTORS;

const highlightedPromises = [];

if (excelData.length > 0) {
for (const entry of excelData) {
if (isEmpty(entry.projectName)) {
continue;
}

const tableElements = await ctx.page.$x(xProjectName(entry.projectName));

if (tableElements.length > 1) {
for (let i = 1; i <= tableElements.length; i++) {
highlightedPromises.push(
`(${xProjectName(entry.projectName)})[${i}]`,
);
}
} else {
highlightedPromises.push(xProjectName(entry.projectName));
}
}
}

await Promise.all(
highlightedPromises.map((selector) => {
return highlightXPath(ctx, selector);
}),
);

console.log('step: highlightCreatedEntriesStep end');
return highlightedPromises;
}
15 changes: 15 additions & 0 deletions src/steps/navigateToProjectManagement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {click, showProgress, waitForXPath, type Context} from '@matterway/sdk';
import {t} from 'i18next';
import {SELECTORS} from 'shared/selectors';

export async function navigateToProjectManagementStep(ctx: Context) {
console.log('step: navigateToProjectManagementStep');
await showProgress(ctx, t('progress.createData'));

const {projects, xAddRecordsBtn} = SELECTORS.navigateToProjectManagement;

await click(ctx, projects);
await waitForXPath(ctx, xAddRecordsBtn);

console.log('step: navigateToProjectManagementStep end');
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3560,7 +3560,7 @@ date-fns@^3.3.1:
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf"
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==

dayjs@^1.8.34:
dayjs@^1.11.11, dayjs@^1.8.34:
version "1.11.11"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
Expand Down

0 comments on commit 228fb5f

Please sign in to comment.