Skip to content

Commit 679445d

Browse files
Fatmerosen-vladimirov
authored andcommitted
feat(Analytics): Respect playground key from package.json file
We need to track users that export their projects from playground and opens them in CLI or Sidekick. To support that we introduce playground key in nativescript key in package.json file. For example: ``` { "nativescript": { "playground": { "id": "some user quid", "usedTutorial": false // is not obligatory. In case it is present, can be true or false } } } ``` If case when package.json file contains playground key, {N} CLI reads playground data and saves them in userSettings file. If usedTutorial=true is already saved in userSettings file, {N} CLI does not overwrite it. After that {N} CLI deletes playground key from package.json file. In case when package.json file does not contain playground key, {N} CLI checks if playground key is already saved in userSettings file. It this is the case, {N} CLI reads playground data from userSettings file.
1 parent 94bda61 commit 679445d

11 files changed

+309
-13
lines changed

PublicAPI.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,29 @@ getUserAgentString(identifier: string): string;
976976
const userAgentString = tns.analyticsSettingsService.getUserAgentString("tns/3.3.0");
977977
```
978978
979+
### getPlaygroundInfo
980+
The `getPlaygroundInfo` method allows retrieving information for projects that are exported from playground
981+
982+
* Definition:
983+
```TypeScript
984+
/**
985+
* Gets information for projects that are exported from playground.
986+
* Returns null in case when project does not have playground key in package.json file (e.g is not exported from playground) and no playground info is saved in userSettings file
987+
* @param {string} projectDir The project directory.
988+
* @returns {Promise<IPlaygroundInfo>} Playground info. { id: string, usedTutorial: boolean }
989+
*/
990+
getPlaygroundInfo(projectDir: string): Promise<IPlaygroundInfo>;
991+
```
992+
993+
* Usage:
994+
```JavaScript
995+
tns.analyticsSettingsService.getPlaygroundInfo("/my/project/path")
996+
.then(playgroundInfo => {
997+
console.log(playgroundInfo.id);
998+
console.log(playgroundInfo.usedTutorial);
999+
});
1000+
```
1001+
9791002
## How to add a new method to Public API
9801003
CLI is designed as command line tool and when it is used as a library, it does not give you access to all of the methods. This is mainly implementation detail. Most of the CLI's code is created to work in command line, not as a library, so before adding method to public API, most probably it will require some modification.
9811004
For example the `$options` injected module contains information about all `--` options passed on the terminal. When the CLI is used as a library, the options are not populated. Before adding method to public API, make sure its implementation does not rely on `$options`.

lib/bootstrap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,5 @@ $injector.requirePublic("extensibilityService", "./services/extensibility-servic
150150
$injector.require("nodeModulesDependenciesBuilder", "./tools/node-modules/node-modules-dependencies-builder");
151151
$injector.require("subscriptionService", "./services/subscription-service");
152152
$injector.require("terminalSpinnerService", "./services/terminal-spinner-service");
153+
154+
$injector.require('playgroundService', './services/playground-service');

lib/definitions/project.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ interface IProjectDataService {
116116
*/
117117
removeDependency(projectDir: string, dependencyName: string): void;
118118

119-
getProjectData(projectDir: string): IProjectData;
119+
getProjectData(projectDir?: string): IProjectData;
120120
}
121121

122122
/**

lib/services/analytics-settings-service.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class AnalyticsSettingsService implements IAnalyticsSettingsService {
88
private $staticConfig: IStaticConfig,
99
private $hostInfo: IHostInfo,
1010
private $osInfo: IOsInfo,
11-
private $logger: ILogger) { }
11+
private $logger: ILogger,
12+
private $playgroundService: IPlaygroundService) { }
1213

1314
public async canDoRequest(): Promise<boolean> {
1415
return true;
@@ -23,6 +24,11 @@ class AnalyticsSettingsService implements IAnalyticsSettingsService {
2324
return this.getSettingValueOrDefault(this.$staticConfig.ANALYTICS_INSTALLATION_ID_SETTING_NAME);
2425
}
2526

27+
@exported("analyticsSettingsService")
28+
public async getPlaygroundInfo(projectDir: string): Promise<IPlaygroundInfo> {
29+
return this.$playgroundService.getPlaygroundInfo(projectDir);
30+
}
31+
2632
public getClientName(): string {
2733
return "" + this.$staticConfig.CLIENT_NAME_ALIAS.cyan.bold;
2834
}

lib/services/analytics/google-analytics-custom-dimensions.d.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

lib/services/analytics/google-analytics-provider.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class GoogleAnalyticsProvider implements IGoogleAnalyticsProvider {
4646
this.setCrossClientCustomDimensions(visitor, sessionId);
4747
break;
4848
default:
49-
this.setCustomDimensions(visitor, trackInfo.customDimensions, sessionId);
49+
await this.setCustomDimensions(visitor, trackInfo.customDimensions, sessionId);
5050
break;
5151
}
5252

@@ -60,7 +60,7 @@ export class GoogleAnalyticsProvider implements IGoogleAnalyticsProvider {
6060
}
6161
}
6262

63-
private setCustomDimensions(visitor: ua.Visitor, customDimensions: IStringDictionary, sessionId: string): void {
63+
private async setCustomDimensions(visitor: ua.Visitor, customDimensions: IStringDictionary, sessionId: string): Promise<void> {
6464
const defaultValues: IStringDictionary = {
6565
[GoogleAnalyticsCustomDimensions.cliVersion]: this.$staticConfig.version,
6666
[GoogleAnalyticsCustomDimensions.nodeVersion]: process.version,
@@ -70,6 +70,12 @@ export class GoogleAnalyticsProvider implements IGoogleAnalyticsProvider {
7070
[GoogleAnalyticsCustomDimensions.client]: AnalyticsClients.Unknown
7171
};
7272

73+
const playgrounInfo = await this.$analyticsSettingsService.getPlaygroundInfo();
74+
if (playgrounInfo && playgrounInfo.id) {
75+
defaultValues[GoogleAnalyticsCustomDimensions.playgroundId] = playgrounInfo.id;
76+
defaultValues[GoogleAnalyticsCustomDimensions.usedTutorial] = playgrounInfo.usedTutorial.toString();
77+
}
78+
7379
customDimensions = _.merge(defaultValues, customDimensions);
7480

7581
_.each(customDimensions, (value, key) => {

lib/services/playground-service.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
export class PlaygroundService implements IPlaygroundService {
2+
constructor(private $fs: IFileSystem,
3+
private $projectDataService: IProjectDataService,
4+
private $userSettingsService: IUserSettingsService) { }
5+
6+
public async getPlaygroundInfo(projectDir?: string): Promise<IPlaygroundInfo> {
7+
const projectData = this.getProjectData(projectDir);
8+
if (projectData) {
9+
const projectFileContent = this.$fs.readJson(projectData.projectFilePath);
10+
if (this.hasPlaygroundKey(projectFileContent)) {
11+
const id = projectFileContent.nativescript.playground.id;
12+
let usedTutorial = projectFileContent.nativescript.playground.usedTutorial || false;
13+
14+
// In case when usedTutorial=true is already saved in userSettings file, we shouldn't overwrite it
15+
const playgroundInfo = await this.getPlaygroundInfoFromUserSettingsFile();
16+
if (playgroundInfo && playgroundInfo.usedTutorial) {
17+
usedTutorial = true;
18+
}
19+
20+
delete projectFileContent.nativescript.playground;
21+
this.$fs.writeJson(projectData.projectFilePath, projectFileContent);
22+
23+
const result = { id , usedTutorial };
24+
await this.$userSettingsService.saveSettings(<any>{playground: result});
25+
return result;
26+
}
27+
}
28+
29+
return this.getPlaygroundInfoFromUserSettingsFile();
30+
}
31+
32+
private getProjectData(projectDir: string): IProjectData {
33+
try {
34+
return this.$projectDataService.getProjectData(projectDir);
35+
} catch (e) {
36+
// in case command is executed in non-project folder
37+
return null;
38+
}
39+
}
40+
41+
private hasPlaygroundKey(projectFileContent: any): boolean {
42+
return projectFileContent && projectFileContent.nativescript && projectFileContent.nativescript.playground && projectFileContent.nativescript.playground.id;
43+
}
44+
45+
private async getPlaygroundInfoFromUserSettingsFile(): Promise<IPlaygroundInfo> {
46+
return this.$userSettingsService.getSettingValue<IPlaygroundInfo>("playground");
47+
}
48+
}
49+
$injector.register('playgroundService', PlaygroundService);

test/platform-commands.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ function createTestInjector() {
163163
})
164164
});
165165
testInjector.register("extensibilityService", {});
166+
testInjector.register("analyticsSettingsService", {
167+
getPlaygroundInfo: () => Promise.resolve(null)
168+
});
166169

167170
return testInjector;
168171
}

test/plugins-service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ function createTestInjector() {
113113
testInjector.register("httpClient", {});
114114
testInjector.register("extensibilityService", {});
115115
testInjector.register("androidPluginBuildService", stubs.AndroidPluginBuildServiceStub);
116+
testInjector.register("analyticsSettingsService", {
117+
getPlaygroundInfo: () => Promise.resolve(null)
118+
});
116119

117120
return testInjector;
118121
}

0 commit comments

Comments
 (0)