Skip to content
19 changes: 19 additions & 0 deletions docs/user-guide/studio-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,22 @@ that analysis. Use the ***--help*** flag to see all options for a specific comma
content-cli pull analysis --help
content-cli push analysis --help
```

## Pull and Push View Bookmarks
Comment thread
manjindersingh98 marked this conversation as resolved.

Enable users to pull and push view (board) bookmarks using content-cli. For pulling view bookmarks
you can specify --type (SHARED/ALL), and by default it fetches USER bookmarks.

```
// Pull view bookmarks
content-cli pull view-bookmarks --profile my-profile-name --id 73d39112-73ae-4bbe-8051-3c0f14e065ec --type SHARED
```

After you have pulled your view bookmarks with the --type option,
it's time to push them inside a view in a different team. You can accomplish this using
the same command as with pushing other assets to Studio:

```
// Push view bookmarks to Studio
content-cli push view-bookmarks -p my-profile-name --id 73d39112-73ae-4bbe-8051-3c0f14e065ec --file studio_view_bookmarks_39c5bb7b-b486-4230-ab01-854a17ddbff2.json
```
39 changes: 39 additions & 0 deletions src/commands/view/module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Commands related to the View feature.
*/

import { Configurator, IModule } from "../../core/command/module-handler";
import { Context } from "../../core/command/cli-context";
import { Command, OptionValues } from "commander";
import { ViewBookmarksCommandService } from "./view-bookmarks-command.service";

class Module extends IModule {

public register(context: Context, configurator: Configurator): void {
const pullCommand = configurator.command("pull");
pullCommand
.command("view-bookmarks")
.description("Command to pull view bookmarks")
.option("--type <type>", "Type of view bookmarks to pull: USER (default), SHARED, or ALL")
Comment thread
manjindersingh98 marked this conversation as resolved.
.requiredOption("--id <id>", "ID of the view (board) to pull bookmarks from")
.action(this.pullViewBookmarks);

const pushCommand = configurator.command("push");
pushCommand
.command("view-bookmarks")
.description("Command to push view bookmarks to a board")
.requiredOption("--id <id>", "ID of the view (board) to push bookmarks into")
.requiredOption("-f, --file <file>", "The file to push")
.action(this.pushViewBookmarks);
}

private async pullViewBookmarks(context: Context, command: Command, options: OptionValues): Promise<void> {
await new ViewBookmarksCommandService(context).pullViewBookmarks(options.id, options.type);
}

private async pushViewBookmarks(context: Context, command: Command, options: OptionValues): Promise<void> {
await new ViewBookmarksCommandService(context).pushViewBookmarks(options.id, options.file);
}
}

export = Module;
18 changes: 18 additions & 0 deletions src/commands/view/view-bookmarks-command.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ViewBookmarksManagerFactory } from "./view-bookmarks.manager-factory";
import { Context } from "../../core/command/cli-context";

export class ViewBookmarksCommandService {
private viewBookmarksManagerFactory: ViewBookmarksManagerFactory;

Check warning on line 5 in src/commands/view/view-bookmarks-command.service.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Member 'viewBookmarksManagerFactory' is never reassigned; mark it as `readonly`.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AZ6szUI1d-C0C1PLghcs&open=AZ6szUI1d-C0C1PLghcs&pullRequest=372

constructor(context: Context) {
this.viewBookmarksManagerFactory = new ViewBookmarksManagerFactory(context);
}

public async pullViewBookmarks(boardId: string, type?: string): Promise<void> {
await this.viewBookmarksManagerFactory.createViewBookmarksManager(null, boardId, type).pull();
Comment thread
cursor[bot] marked this conversation as resolved.
}

public async pushViewBookmarks(boardId: string, filename: string): Promise<void> {
await this.viewBookmarksManagerFactory.createViewBookmarksManager(filename, boardId).push();
}
}
37 changes: 37 additions & 0 deletions src/commands/view/view-bookmarks.manager-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as fs from "fs";

Check warning on line 1 in src/commands/view/view-bookmarks.manager-factory.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `node:fs` over `fs`.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AZ6szUI7d-C0C1PLghct&open=AZ6szUI7d-C0C1PLghct&pullRequest=372
import * as path from "path";

Check warning on line 2 in src/commands/view/view-bookmarks.manager-factory.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `node:path` over `path`.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AZ6szUI7d-C0C1PLghcu&open=AZ6szUI7d-C0C1PLghcu&pullRequest=372
import { ViewBookmarksManager } from "./view-bookmarks.manager";
import { FatalError, logger } from "../../core/utils/logger";
import { Context } from "../../core/command/cli-context";

export class ViewBookmarksManagerFactory {

private readonly context: Context;

constructor(context: Context) {
this.context = context;
}

public createViewBookmarksManager(
filename: string,
boardId: string,
type?: string
Comment thread
manjindersingh98 marked this conversation as resolved.
Outdated
): ViewBookmarksManager {
const viewBookmarksManager = new ViewBookmarksManager(this.context);
viewBookmarksManager.boardId = boardId;
type = (type ?? "USER").toUpperCase();

viewBookmarksManager.type = type;
if (filename !== null) {
viewBookmarksManager.fileName = this.readFile(filename);
}
return viewBookmarksManager;
}

private readFile(fileName: string): string {
Comment thread
manjindersingh98 marked this conversation as resolved.
Outdated
if (!fs.existsSync(path.resolve(process.cwd(), fileName))) {
logger.error(new FatalError("The provided file does not exist"));
}
return path.resolve(process.cwd(), fileName);
}
}
63 changes: 63 additions & 0 deletions src/commands/view/view-bookmarks.manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as fs from "fs";

Check warning on line 1 in src/commands/view/view-bookmarks.manager.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `node:fs` over `fs`.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AZ6szUFxd-C0C1PLghcp&open=AZ6szUFxd-C0C1PLghcp&pullRequest=372
import * as FormData from "form-data";
import { Context } from "../../core/command/cli-context";
import { BaseManager } from "../../core/http/http-shared/base.manager";
import { ManagerConfig } from "../../core/http/http-shared/manager-config.interface";

export class ViewBookmarksManager extends BaseManager {
private static BASE_URL = "/blueprint/api/bookmarks";

Check warning on line 8 in src/commands/view/view-bookmarks.manager.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Member 'BASE_URL' is never reassigned; mark it as `readonly`.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AZ6szUFxd-C0C1PLghcq&open=AZ6szUFxd-C0C1PLghcq&pullRequest=372
private static VIEW_BOOKMARKS_FILE_PREFIX = "studio_view_bookmarks_";

Check warning on line 9 in src/commands/view/view-bookmarks.manager.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Member 'VIEW_BOOKMARKS_FILE_PREFIX' is never reassigned; mark it as `readonly`.

See more on https://sonarcloud.io/project/issues?id=celonis_content-cli&issues=AZ6szUFxd-C0C1PLghcr&open=AZ6szUFxd-C0C1PLghcr&pullRequest=372

private _boardId: string;
private _fileName: string;
private _type: string;

constructor(context: Context) {
super(context);
}

public get fileName(): string {
return this._fileName;
}

public set fileName(value: string) {
this._fileName = value;
}

public get boardId(): string {
return this._boardId;
}

public set boardId(value: string) {
this._boardId = value;
}

public get type(): string {
return this._type;
}

public set type(value: string) {
this._type = value;
}

public getConfig(): ManagerConfig {
return {
pushUrl: `${ViewBookmarksManager.BASE_URL}/import?boardId=${encodeURIComponent(this.boardId)}`,
pullUrl: `${ViewBookmarksManager.BASE_URL}/export?boardId=${encodeURIComponent(this.boardId)}&type=${encodeURIComponent(this.type)}`,
exportFileName: `${ViewBookmarksManager.VIEW_BOOKMARKS_FILE_PREFIX}${this.boardId}.json`,
onPushSuccessMessage: (): string => {
return "View Bookmarks were pushed successfully.";
},
Comment thread
manjindersingh98 marked this conversation as resolved.
};
}

public getBody(): any {
const formData = new FormData();
formData.append("file", fs.createReadStream(this.fileName));
return formData;
}

protected getSerializedFileContent(data: any): string {
return JSON.stringify(data);
}
}
Loading