Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(marketplace): added ability to install/uninstall tools #100

Merged
merged 16 commits into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/application/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
},
"marketplace": {
"title": "Marketplace",
"listOfTools": "Tools"
"listOfTools": "Tools",
"uninstallTool": "Uninstall",
"installTool": "Install"
}
}
49 changes: 40 additions & 9 deletions src/application/services/useMarketplace.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,65 @@
import type EditorTool from '@/domain/entities/EditorTool';
import { type Ref, ref, onMounted } from 'vue';
import { type Ref, ref, watch, onMounted } from 'vue';
import { marketplaceService } from '@/domain';
import type { EditorToolWithUserBinding } from '@/domain/entities/EditorTool';
import { useAppState } from './useAppState';
import type EditorTool from '@/domain/entities/EditorTool';

/**
* Composable for the application state
*/
interface UseMarketplaceComposable {
/**
* All editor tools that are used in notes creation
* List of tools with information, if they are installed by the user
*/
tools: Ref<EditorTool[]>;
tools: Ref<EditorToolWithUserBinding[]>;
}

/**
* Application service for working with the Editor Tools
*/
export default function (): UseMarketplaceComposable {
const toolsWithUserBindings = ref<EditorToolWithUserBinding[]>([]);
const availableTools = ref<EditorTool[]>([]);

/**
* All editor tools
* Create a list of tools with information, if they are installed by the user
*
* @param tools - list of all tools
* @param userTools - list of user tools
*/
const tools = ref<EditorTool[]>([]);
const getToolsWithUserBindings = (tools: EditorTool[], userTools: EditorTool[]): EditorToolWithUserBinding[] => {
return tools.map((tool) => {
return {
...tool,
isInstalled: userTools.some((userTool) => userTool.id === tool.id),
};
});
};

/**
* Get list of all tools
* User tools
*/
const { userEditorTools } = useAppState();

onMounted(async () => {
tools.value = await marketplaceService.getAllTools();
availableTools.value = await marketplaceService.getAllTools();
toolsWithUserBindings.value = getToolsWithUserBindings(availableTools.value, userEditorTools.value);
});

/**
* Check if user tools are changed
*/
watch(
userEditorTools,
async (newValue) => {
toolsWithUserBindings.value = getToolsWithUserBindings(availableTools.value, newValue);
},
{
immediate: true,
}
);

return {
tools: tools,
tools: toolsWithUserBindings,
};
}
21 changes: 18 additions & 3 deletions src/application/services/useUserSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ interface UseUserSettingsComposableState {
/**
* Add tool to the user settings
*/
addTool(id: string): void;
addTool(id: string): Promise<void>;

/**
* Remove tool from the user settings
*/
removeTool(id: string): Promise<void>;
}

/**
Expand All @@ -19,11 +24,21 @@ export function useUserSettings(): UseUserSettingsComposableState {
*
* @param id - Tool identifier
*/
function addTool(id: string): void {
userService.addTool(id);
async function addTool(id: string): Promise<void> {
await userService.addTool(id);
}

/**
* Remove tool from the user settings
*
* @param id - Tool identifier
*/
async function removeTool(id: string): Promise<void> {
await userService.removeTool(id);
}

return {
addTool,
removeTool,
};
}
10 changes: 10 additions & 0 deletions src/domain/entities/EditorTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,13 @@ export default interface EditorTool {
cdn?: string;
};
}

/**
* Editor tool with user binding
*/
export interface EditorToolWithUserBinding extends EditorTool {
/**
* Is tool included in user's editor settings
*/
isInstalled: boolean;
}
2 changes: 0 additions & 2 deletions src/domain/marketplace.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ export default class MarketplaceService {
/**
* Service constructor
*
* @param eventBus - Common domain event bus
* @param marketplaceRepository - repository instance
* @param marketplaceRepositoryRepository
*/
constructor(marketplaceRepository: MarketplaceRepository) {
this.repository = marketplaceRepository;
Expand Down
10 changes: 9 additions & 1 deletion src/domain/user.repository.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ export default interface UserRepositoryInterface {
* Returns array of editor tools
*/
getUserEditorTools: () => EditorTool[];

/**
* Adds a tool to the user (marketplace mock)
*
* @param id - tool id
*/
addTool: (id: string) => void;
addTool: (id: string) => Promise<void>;

/**
* Removes a tool from the user (marketplace mock)
*
* @param id - tool id
*/
removeTool: (id: string) => Promise<void>;
}
13 changes: 11 additions & 2 deletions src/domain/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,16 @@ export default class UserService {
*
* @param id - tool id
*/
public addTool(id: string): void {
this.repository.addTool(id);
public async addTool(id: string): Promise<void> {
return await this.repository.addTool(id);
}

/**
* Removes a tool from the user
*
* @param id - tool id
*/
public async removeTool(id: string): Promise<void> {
return await this.repository.removeTool(id);
}
}
18 changes: 18 additions & 0 deletions src/infrastructure/storage/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,22 @@ export class UserStore extends SubscribableStore<UserStoreData> {
public setUserEditorTools(editorTools: EditorTool[]): void {
this.data.editorTools = editorTools;
}

/**
* Adds a tool to the user
*
* @param editorTool - tool to add
*/
public addEditorTool(editorTool: EditorTool): void {
this.data.editorTools = [...this.data.editorTools, editorTool];
}

/**
* Removes a tool from the user
*
* @param id - tool id
*/
public removeEditorTool(id: EditorTool['id']): void {
this.data.editorTools = this.data.editorTools.filter((tool) => tool.id !== id);
}
}
19 changes: 16 additions & 3 deletions src/infrastructure/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,28 @@ export default class UserRepository extends Repository<UserStore, UserStoreData>
}

/**
* Adds a tool to the user (marketplace mock)
* Adds a tool to the user
*
* @param id - tool id
*/
public async addTool(id: string): Promise<void> {
const response = await this.transport.post<{ toolId: string }>('/user/editor-tools', {
const res = await this.transport.post<{ addedTool: EditorTool }>('/user/editor-tools', {
toolId: id,
});

console.log('Add tool response', response);
this.store.addEditorTool(res.addedTool);
}

/**
* Removes a tool from the user
*
* @param id - tool id
*/
public async removeTool(id: string): Promise<void> {
const res = await this.transport.delete<{ removedId: EditorTool['id'] }>('/user/editor-tools', {
toolId: id,
});

this.store.removeEditorTool(res.removedId);
}
}
45 changes: 45 additions & 0 deletions src/presentation/components/marketplace/EditorToolElement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<li>
<div class="marketplace__tool">
{{ tool.title }}
<Button
v-if="canBeUninstalled"
:disabled="tool.isDefault"
:text="t('marketplace.uninstallTool')"
@click="removeTool(tool.id)"
/>
<Button
v-if="canBeInstalled"
:text="t('marketplace.installTool')"
type="transparent"
@click="addTool(tool.id)"
/>
</div>
</li>
</template>

<script setup lang="ts">
import { EditorToolWithUserBinding } from '@/domain/entities/EditorTool';
import { useUserSettings } from '@/application/services/useUserSettings';
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
import Button from '../button/Button.vue';
const { addTool, removeTool } = useUserSettings();

const { t } = useI18n();

const props = defineProps<{
tool: EditorToolWithUserBinding;
}>();

const canBeUninstalled = computed(() => !props.tool.isDefault && props.tool.isInstalled);
const canBeInstalled = computed(() => !props.tool.isDefault && !props.tool.isInstalled);
</script>

<style scoped lang="postcss">
.marketplace__tool {
display: flex;
align-items: center;
gap: var(--spacing-very-x);
}
</style>
5 changes: 2 additions & 3 deletions src/presentation/pages/Marketplace.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
v-for="tool in tools"
:key="tool.id"
>
<li>
{{ tool.title }}
</li>
<EditorToolElement :tool="tool" />
</ul>
</div>
</template>

<script setup lang="ts">
import useMarketplace from '@/application/services/useMarketplace';
import EditorToolElement from '../components/marketplace/EditorToolElement.vue';

const { tools } = useMarketplace();
</script>
Expand Down
Loading