mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-10 18:03:47 +00:00
Sheets settings (#774)
* wip: migrate sheet settings --------- Co-authored-by: arc-alex <ac@omnivox.dk>
This commit is contained in:
@@ -661,12 +661,13 @@ export async function uploadSheetClientFile(req, res: Response) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description STEP-1 GET Client Secrect status
|
||||
* @description STEP-1 GET Client Secret status
|
||||
*/
|
||||
export const getClientSecrect = async (req: Request, res: Response) => {
|
||||
export const getClientSecret = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const clientSecrectExists = await sheet.testClientSecret();
|
||||
if (clientSecrectExists) {
|
||||
// TODO: can we merge this with the previous?
|
||||
const clientSecretExists = await sheet.testClientSecret();
|
||||
if (clientSecretExists) {
|
||||
res.status(200).send();
|
||||
} else {
|
||||
res.status(500).send({ message: 'The Client ID does not exist' });
|
||||
@@ -706,11 +707,11 @@ export const getAuthentication = async (_req: Request, res: Response) => {
|
||||
*/
|
||||
export const postId = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id } = req.body;
|
||||
if (id.lenght < 40) {
|
||||
res.status(400).send({ message: 'ID is usualy 44 characters long' });
|
||||
const { sheetId } = req.body;
|
||||
if (sheetId.length < 40) {
|
||||
res.status(400).send({ message: 'ID is usually 44 characters long' });
|
||||
}
|
||||
const state = await sheet.testSheetId(id);
|
||||
const state = await sheet.testSheetId(sheetId);
|
||||
res.status(200).send(state);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
@@ -722,8 +723,8 @@ export const postId = async (req: Request, res: Response) => {
|
||||
*/
|
||||
export const postWorksheet = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { worksheet, id } = req.body;
|
||||
const state = await sheet.testWorksheet(worksheet, id);
|
||||
const { sheetId, worksheet } = req.body;
|
||||
const state = await sheet.testWorksheet(sheetId, worksheet);
|
||||
res.status(200).send(state);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
@@ -731,13 +732,15 @@ export const postWorksheet = async (req: Request, res: Response) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @description STEP-5 POST download undown to sheet
|
||||
* @description STEP-5 POST download rundown to sheet
|
||||
* @returns parsed result
|
||||
*/
|
||||
export async function pullSheet(req: Request, res: Response) {
|
||||
try {
|
||||
const { id, options } = req.body;
|
||||
const data = await sheet.pull(id, options);
|
||||
const { sheetId, options } = req.body;
|
||||
console.log('starting');
|
||||
const data = await sheet.pull(sheetId, options);
|
||||
console.log('finished');
|
||||
res.status(200).send(data);
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
@@ -749,8 +752,8 @@ export async function pullSheet(req: Request, res: Response) {
|
||||
*/
|
||||
export async function pushSheet(req: Request, res: Response) {
|
||||
try {
|
||||
const { id, options } = req.body;
|
||||
await sheet.push(id, options);
|
||||
const { sheetId, options } = req.body;
|
||||
await sheet.push(sheetId, options);
|
||||
res.status(200).send();
|
||||
} catch (error) {
|
||||
res.status(500).send({ message: String(error) });
|
||||
|
||||
@@ -244,8 +244,8 @@ export const validateProjectFiles = (projectFiles: { filename?: string; newFilen
|
||||
return errors;
|
||||
};
|
||||
|
||||
export const validateSheetid = [
|
||||
body('id').exists().isString(),
|
||||
export const validateSheetId = [
|
||||
body('sheetId').exists().isString(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
@@ -255,7 +255,7 @@ export const validateSheetid = [
|
||||
];
|
||||
|
||||
export const validateWorksheet = [
|
||||
body('id').exists().isString(),
|
||||
body('sheetId').exists().isString(),
|
||||
body('worksheet').exists().isString(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -266,7 +266,7 @@ export const validateWorksheet = [
|
||||
];
|
||||
|
||||
export const validateSheetOptions = [
|
||||
body('id').exists().isString(),
|
||||
body('sheetId').exists().isString(),
|
||||
// body('options').exists().isObject(), TODO:
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
|
||||
@@ -31,7 +31,8 @@ import {
|
||||
pushSheet,
|
||||
postId,
|
||||
getAuthentication,
|
||||
getClientSecrect as getClientSecret,
|
||||
getClientSecret as getClientSecret,
|
||||
postWorksheet,
|
||||
} from '../controllers/ontimeController.js';
|
||||
|
||||
import {
|
||||
@@ -45,7 +46,7 @@ import {
|
||||
validateProjectDuplicate,
|
||||
validateLoadProjectFile,
|
||||
validateProjectRename,
|
||||
validateSheetid,
|
||||
validateSheetId,
|
||||
validateWorksheet,
|
||||
validateSheetOptions,
|
||||
} from '../controllers/ontimeController.validate.js';
|
||||
@@ -126,6 +127,7 @@ router.post('/project', projectSanitiser, createProjectFile);
|
||||
// create route between controller and '/ontime/project/:filename' endpoint
|
||||
router.delete('/project/:filename', sanitizeProjectFilename, deleteProjectFile);
|
||||
|
||||
// TODO: move the google sheet stuff into a separate file
|
||||
// Google Sheet integration - Step 1
|
||||
router.post('/sheet/clientsecret', uploadFile, uploadClientSecret);
|
||||
router.get('/sheet/clientsecret', uploadFile, getClientSecret);
|
||||
@@ -135,13 +137,13 @@ router.get('/sheet/authentication/url', getAuthenticationUrl);
|
||||
router.get('/sheet/authentication', getAuthentication);
|
||||
|
||||
// Google Sheet integration - Step 3
|
||||
router.post('/sheet/id', validateSheetid, postId);
|
||||
router.post('/sheet/sheetId', validateSheetId, postId);
|
||||
|
||||
// Google Sheet integration - Step 4
|
||||
router.post('/sheet/worksheet', validateWorksheet, postId);
|
||||
router.post('/sheet/worksheet', validateWorksheet, postWorksheet);
|
||||
|
||||
// Google Sheet integration - Step 5
|
||||
router.post('/sheet/pull', validateSheetOptions, pullSheet);
|
||||
router.post('/sheet-pull', validateSheetOptions, pullSheet);
|
||||
|
||||
// Google Sheet integration - Step 6
|
||||
router.post('/sheet-push', validateSheetOptions, pushSheet);
|
||||
|
||||
@@ -80,7 +80,7 @@ class Sheet {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description STEP 1 - test that the saved object is pressent
|
||||
* @description STEP 1 - test that the saved object is present
|
||||
*/
|
||||
testClientSecret() {
|
||||
return Sheet.clientSecret !== null;
|
||||
@@ -92,18 +92,15 @@ class Sheet {
|
||||
* @throws
|
||||
*/
|
||||
async openAuthServer(): Promise<string | null> {
|
||||
//TODO: this only works on local networks
|
||||
//TODO: this only works in local networks
|
||||
|
||||
// if the server is allready running retun it
|
||||
// if the server is already running return it
|
||||
if (Sheet.authUrl) {
|
||||
clearTimeout(this.authServerTimeout);
|
||||
this.authServerTimeout = setTimeout(
|
||||
() => {
|
||||
Sheet.authUrl = null;
|
||||
server.unref();
|
||||
},
|
||||
2 * 60 * 1000,
|
||||
);
|
||||
this.authServerTimeout = setTimeout(() => {
|
||||
Sheet.authUrl = null;
|
||||
server.unref();
|
||||
}, 120000);
|
||||
return Sheet.authUrl;
|
||||
}
|
||||
|
||||
@@ -209,12 +206,12 @@ class Sheet {
|
||||
* @description STEP 3 - test the given sheet id
|
||||
* @throws
|
||||
*/
|
||||
async testSheetId(id: string) {
|
||||
async testSheetId(sheetId: string) {
|
||||
const spreadsheets = await sheets({ version: 'v4', auth: Sheet.client }).spreadsheets.get({
|
||||
spreadsheetId: id,
|
||||
spreadsheetId: sheetId,
|
||||
includeGridData: false,
|
||||
});
|
||||
if (spreadsheets.status != 200) {
|
||||
if (spreadsheets.status !== 200) {
|
||||
throw new Error(spreadsheets.statusText);
|
||||
}
|
||||
return { worksheetOptions: spreadsheets.data.sheets.map((i) => i.properties.title) };
|
||||
@@ -224,12 +221,12 @@ class Sheet {
|
||||
* @description STEP 4 - test the given worksheet
|
||||
* @throws
|
||||
*/
|
||||
async testWorksheet(id: string, worksheet: string) {
|
||||
async testWorksheet(sheetId: string, worksheet: string) {
|
||||
const spreadsheets = await sheets({ version: 'v4', auth: Sheet.client }).spreadsheets.get({
|
||||
spreadsheetId: id,
|
||||
spreadsheetId: sheetId,
|
||||
includeGridData: false,
|
||||
});
|
||||
if (spreadsheets.status != 200) {
|
||||
if (spreadsheets.status !== 200) {
|
||||
throw new Error(spreadsheets.statusText);
|
||||
}
|
||||
const worksheetExist = spreadsheets.data.sheets.find((i) => i.properties.title === worksheet);
|
||||
@@ -250,17 +247,18 @@ class Sheet {
|
||||
spreadsheetId: sheetId,
|
||||
});
|
||||
|
||||
if (spreadsheets.status === 200) {
|
||||
const ourWorksheetData = spreadsheets.data.sheets.find((n) => n.properties.title == worksheet);
|
||||
if (ourWorksheetData !== undefined) {
|
||||
const endCell = getA1Notation(
|
||||
ourWorksheetData.properties.gridProperties.rowCount,
|
||||
ourWorksheetData.properties.gridProperties.columnCount,
|
||||
);
|
||||
return { worksheetId: ourWorksheetData.properties.sheetId, range: `${worksheet}!A1:${endCell}` };
|
||||
}
|
||||
} else {
|
||||
throw new Error('Uable to open spreadsheets');
|
||||
if (spreadsheets.status !== 200) {
|
||||
throw new Error(`Request failed: ${spreadsheets.status} ${spreadsheets.statusText}`);
|
||||
}
|
||||
|
||||
const ourWorksheetData = spreadsheets.data.sheets.find((n) => n.properties.title == worksheet);
|
||||
|
||||
if (ourWorksheetData !== undefined) {
|
||||
const endCell = getA1Notation(
|
||||
ourWorksheetData.properties.gridProperties.rowCount,
|
||||
ourWorksheetData.properties.gridProperties.columnCount,
|
||||
);
|
||||
return { worksheetId: ourWorksheetData.properties.sheetId, range: `${worksheet}!A1:${endCell}` };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +300,7 @@ class Sheet {
|
||||
updateRundown.push({
|
||||
deleteDimension: { range: { dimension: 'ROWS', startIndex: titleRow + 2, sheetId: worksheetId } },
|
||||
});
|
||||
// insert the lenght of the rundown
|
||||
// insert the length of the rundown
|
||||
updateRundown.push({
|
||||
insertDimension: {
|
||||
inheritFromBefore: false,
|
||||
@@ -340,19 +338,19 @@ class Sheet {
|
||||
}
|
||||
|
||||
/**
|
||||
* @description STEP 5 - Downpload the rundown from sheet
|
||||
* @param {string} id - id of the sheet https://docs.google.com/spreadsheets/d/[[spreadsheetId]]/edit#gid=0
|
||||
* @description STEP 5 - Download the rundown from sheet
|
||||
* @param {string} sheetId - id of the sheet https://docs.google.com/spreadsheets/d/[[spreadsheetId]]/edit#gid=0
|
||||
* @param {ExcelImportMap} options
|
||||
* @returns {Promise<Partial<ResponseOK>>}
|
||||
* @throws
|
||||
*/
|
||||
public async pull(id: string, options: ExcelImportMap): Promise<Partial<ResponseOK>> {
|
||||
const { range } = await this.exist(id, options.worksheet);
|
||||
public async pull(sheetId: string, options: ExcelImportMap): Promise<Partial<ResponseOK>> {
|
||||
const { range } = await this.exist(sheetId, options.worksheet);
|
||||
|
||||
const res: Partial<ResponseOK> = {};
|
||||
|
||||
const googleResponse = await sheets({ version: 'v4', auth: Sheet.client }).spreadsheets.values.get({
|
||||
spreadsheetId: id,
|
||||
spreadsheetId: sheetId,
|
||||
valueRenderOption: 'FORMATTED_VALUE',
|
||||
majorDimension: 'ROWS',
|
||||
range,
|
||||
|
||||
Reference in New Issue
Block a user