♻️ OOConnector: refactor a bit of string manipulation
This commit is contained in:
committed by
ericlinagora
parent
6534f23cc2
commit
ca267df7ac
@@ -7,6 +7,7 @@ import { DriveFileType } from '@/interfaces/drive.interface';
|
|||||||
import fileService from '@/services/file.service';
|
import fileService from '@/services/file.service';
|
||||||
import { OfficeToken } from '@/interfaces/routes.interface';
|
import { OfficeToken } from '@/interfaces/routes.interface';
|
||||||
import loggerService from '@/services/logger.service';
|
import loggerService from '@/services/logger.service';
|
||||||
|
import * as Utils from '@/utils';
|
||||||
|
|
||||||
interface RequestQuery {
|
interface RequestQuery {
|
||||||
mode: string;
|
mode: string;
|
||||||
@@ -89,10 +90,13 @@ class IndexController {
|
|||||||
);
|
);
|
||||||
|
|
||||||
res.redirect(
|
res.redirect(
|
||||||
`${SERVER_ORIGIN ?? ''}/${SERVER_PREFIX.replace(
|
Utils.joinURL([SERVER_ORIGIN ?? '', SERVER_PREFIX, 'editor'], {
|
||||||
/(\/+$|^\/+)/gm,
|
token,
|
||||||
'',
|
file_id,
|
||||||
)}/editor?office_token=${officeToken}&token=${token}&file_id=${file_id}&company_id=${company_id}&preview=${preview}`,
|
company_id,
|
||||||
|
preview,
|
||||||
|
office_token: officeToken,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
@@ -126,7 +130,7 @@ class IndexController {
|
|||||||
|
|
||||||
res.render('index', {
|
res.render('index', {
|
||||||
...initResponse,
|
...initResponse,
|
||||||
server: SERVER_ORIGIN.replace(/\/+$/, '') + '/' + SERVER_PREFIX.replace(/(\/+$|^\/+)/, '') || `${req.protocol}://${req.get('host')}/`,
|
server: Utils.joinURL([SERVER_ORIGIN, SERVER_PREFIX]),
|
||||||
token: inPageToken,
|
token: inPageToken,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
import axios, { Axios, AxiosRequestConfig, AxiosResponse } from 'axios';
|
import axios, { Axios, AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||||
import { CREDENTIALS_ENDPOINT, CREDENTIALS_ID, CREDENTIALS_SECRET, ONLY_OFFICE_SERVER } from '@config';
|
import { CREDENTIALS_ENDPOINT, CREDENTIALS_ID, CREDENTIALS_SECRET, ONLY_OFFICE_SERVER } from '@config';
|
||||||
import loggerService from './logger.service';
|
import loggerService from './logger.service';
|
||||||
|
import * as Utils from '@/utils';
|
||||||
|
|
||||||
/** Client for the Twake Drive backend API on behalf of the plugin (or provided token in parameters) */
|
/** Client for the Twake Drive backend API on behalf of the plugin (or provided token in parameters) */
|
||||||
class ApiService implements IApiService {
|
class ApiService implements IApiService {
|
||||||
@@ -73,7 +74,7 @@ class ApiService implements IApiService {
|
|||||||
private refreshToken = async (): Promise<string> => {
|
private refreshToken = async (): Promise<string> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post<IApiServiceApplicationTokenRequestParams, { data: IApiServiceApplicationTokenResponse }>(
|
const response = await axios.post<IApiServiceApplicationTokenRequestParams, { data: IApiServiceApplicationTokenResponse }>(
|
||||||
`${CREDENTIALS_ENDPOINT.replace(/\/$/, '')}/api/console/v1/login`,
|
Utils.joinURL([CREDENTIALS_ENDPOINT, '/api/console/v1/login']),
|
||||||
{
|
{
|
||||||
id: CREDENTIALS_ID,
|
id: CREDENTIALS_ID,
|
||||||
secret: CREDENTIALS_SECRET,
|
secret: CREDENTIALS_SECRET,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { EditConfigInitResult, IEditorService, ModeParametersType } from '@/interfaces/editor.interface';
|
import { EditConfigInitResult, IEditorService, ModeParametersType } from '@/interfaces/editor.interface';
|
||||||
import { UserType } from '@/interfaces/user.interface';
|
import { UserType } from '@/interfaces/user.interface';
|
||||||
import { ONLY_OFFICE_SERVER } from '@config';
|
import { ONLY_OFFICE_SERVER } from '@config';
|
||||||
|
import * as Utils from '@/utils';
|
||||||
|
|
||||||
class EditorService implements IEditorService {
|
class EditorService implements IEditorService {
|
||||||
public init = async (
|
public init = async (
|
||||||
@@ -12,12 +13,14 @@ class EditorService implements IEditorService {
|
|||||||
file_id: string,
|
file_id: string,
|
||||||
): Promise<EditConfigInitResult> => {
|
): Promise<EditConfigInitResult> => {
|
||||||
const { color, mode: fileMode } = this.getFileMode(file_name);
|
const { color, mode: fileMode } = this.getFileMode(file_name);
|
||||||
|
let [, extension] = Utils.splitFilename(file_name);
|
||||||
|
|
||||||
|
extension = extension.toLocaleLowerCase();
|
||||||
return {
|
return {
|
||||||
color,
|
color,
|
||||||
file_id,
|
file_id,
|
||||||
file_version_id,
|
file_version_id,
|
||||||
file_type: file_name.split('.').pop(),
|
file_type: extension,
|
||||||
filename: file_name,
|
filename: file_name,
|
||||||
language: user.preferences.locale || 'en',
|
language: user.preferences.locale || 'en',
|
||||||
mode: fileMode,
|
mode: fileMode,
|
||||||
@@ -32,7 +35,8 @@ class EditorService implements IEditorService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private getFileMode = (filename: string): ModeParametersType => {
|
private getFileMode = (filename: string): ModeParametersType => {
|
||||||
const extension = filename.split('.').pop();
|
let [, extension] = Utils.splitFilename(filename);
|
||||||
|
extension = extension.toLocaleLowerCase();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ import apiService from './api.service';
|
|||||||
import loggerService from './logger.service';
|
import loggerService from './logger.service';
|
||||||
import { Stream } from 'stream';
|
import { Stream } from 'stream';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
|
import * as Utils from '@/utils';
|
||||||
|
|
||||||
class FileService implements IFileService {
|
class FileService implements IFileService {
|
||||||
|
|
||||||
public get = async (params: FileRequestParams): Promise<FileType> => {
|
public get = async (params: FileRequestParams): Promise<FileType> => {
|
||||||
try {
|
try {
|
||||||
const { company_id, file_id } = params;
|
const { company_id, file_id } = params;
|
||||||
@@ -55,7 +57,7 @@ class FileService implements IFileService {
|
|||||||
|
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
|
|
||||||
const nameSplit = (originalFile.metadata.name || '').split('.');
|
const nameSplit = Utils.splitFilename(originalFile.metadata.name || '');
|
||||||
const filename =
|
const filename =
|
||||||
nameSplit[0].replace(/-[0-9]{8}-[0-9]{4}$/, '') +
|
nameSplit[0].replace(/-[0-9]{8}-[0-9]{4}$/, '') +
|
||||||
(!create_new ? '.' : `-${new Date().toISOString().split('.')[0].split(':').slice(0, 2).join('').replace(/-/gm, '').split('T').join('-')}.`) +
|
(!create_new ? '.' : `-${new Date().toISOString().split('.')[0].split(':').slice(0, 2).join('').replace(/-/gm, '').split('T').join('-')}.`) +
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/** Return the key in `obj` of which the value matches the `value` parameter, or `undefined` */
|
||||||
|
export function getKeyForValue<T>(value: T, obj: any): string | undefined {
|
||||||
|
return (Object.entries(obj as { [key: string]: T }).filter(([_key, entryValue]) => value === entryValue)[0] ?? [])[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Same as `getKeyForValue` but returns a default string for values not found */
|
||||||
|
export function getKeyForValueSafe<T>(value: T, obj: any, valueKind: string): string {
|
||||||
|
const result = getKeyForValue(value, obj);
|
||||||
|
return result ?? `(Unknown ${valueKind}: ${JSON.stringify(value)})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Suitable type for query arguments */
|
||||||
|
export type QueryParams = { [key: string]: string | number };
|
||||||
|
|
||||||
|
/** Compose a URL removing and adding slashes and query parameters as warranted */
|
||||||
|
export function joinURL(path: string[], params?: QueryParams) {
|
||||||
|
let joinedPath = path.map(x => x.replace(/(?:^\/+)+|(?:\/+$)/g, "")).join("/");
|
||||||
|
if (path[path.length - 1].endsWith("/"))
|
||||||
|
joinedPath += "/";
|
||||||
|
const paramEntries = Object.entries(params || {});
|
||||||
|
if (paramEntries.length === 0)
|
||||||
|
return joinedPath;
|
||||||
|
const query = paramEntries.map((p) => p.map(encodeURIComponent).join("=")).join("&");
|
||||||
|
return joinedPath + (joinedPath.indexOf("?") > -1 ? "&" : "?") + query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Split a filename into an array `[name, extension]`. Either and both can be
|
||||||
|
* the empty string. When the extension is the whole name, it is assumed to be
|
||||||
|
* the name and not the extension.
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* splitFilename("") // [ "", "" ]
|
||||||
|
* splitFilename(".") // [ ".", "" ]
|
||||||
|
* splitFilename("..") // [ ".", "" ]
|
||||||
|
* splitFilename("filename") // [ "filename", "" ]
|
||||||
|
* splitFilename(".dotfile") // [ ".dotfile", "" ]
|
||||||
|
* splitFilename("a.dotfile") // [ "a", "dotfile" ]
|
||||||
|
* splitFilename(".a.dotfile") // [ ".a", "dotfile" ]
|
||||||
|
* splitFilename("a.b.dotfile") // [ "a.b", "dotfile" ]
|
||||||
|
* splitFilename(".a.b.dotfile") // [ ".a.b", "dotfile" ]
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function splitFilename(filename: string): [string, string] {
|
||||||
|
const parts = filename.split('.');
|
||||||
|
if (parts.length < 2 || (parts.length == 2 && parts[0] === ""))
|
||||||
|
return [filename, ""];
|
||||||
|
const extension = parts.pop();
|
||||||
|
return [parts.join("."), extension];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user