chore: remove files and lists
This commit is contained in:
parent
ba555590ee
commit
165ac3349d
28 changed files with 11 additions and 411 deletions
|
@ -7,8 +7,7 @@ import TheBrandLogo from "./TheBrandLogo.vue";
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<TheBrandLogo class="logo" />
|
<TheBrandLogo class="logo" />
|
||||||
<BaseNav>
|
<BaseNav>
|
||||||
<RouterLink :to="{ name: 'email_files' }">Файлы</RouterLink>
|
<RouterLink :to="{ name: 'audience_contacts' }">Контакты</RouterLink>
|
||||||
<RouterLink :to="{ name: 'audience' }">Аудитория</RouterLink>
|
|
||||||
</BaseNav>
|
</BaseNav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from "vue";
|
|
||||||
import { useFilesTableStore } from "./store";
|
|
||||||
import { formatDate } from "@/shared/lib/utils/date";
|
|
||||||
|
|
||||||
const filesStore = useFilesTableStore();
|
|
||||||
|
|
||||||
const columns = computed(() => [
|
|
||||||
{ key: "name", title: "Название" },
|
|
||||||
{ key: "createdAt", title: "Дата создания" },
|
|
||||||
]);
|
|
||||||
|
|
||||||
filesStore.fetchMany();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<BaseTable
|
|
||||||
:loading="filesStore.loading"
|
|
||||||
:columns="columns"
|
|
||||||
:dataItems="filesStore.files"
|
|
||||||
>
|
|
||||||
<template #createdAt="{ dataItem }">
|
|
||||||
{{ formatDate(dataItem.createdAt) }}
|
|
||||||
</template>
|
|
||||||
</BaseTable>
|
|
||||||
</template>
|
|
|
@ -1,3 +0,0 @@
|
||||||
export { default as FilesTable } from "./FilesTable.vue";
|
|
||||||
export * from "./ports";
|
|
||||||
export { FILES_TABLE_API_PROVIDE_KEY } from "./store";
|
|
|
@ -1,4 +0,0 @@
|
||||||
import type { BaseFetchManyApiPort } from "@/shared/lib/ports";
|
|
||||||
import type { AppFile } from "../domain";
|
|
||||||
|
|
||||||
export type FilesTableApiPort = BaseFetchManyApiPort<AppFile>;
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { useLoader } from "@/shared/lib/composables/loader";
|
|
||||||
import { defineInjectKey, validInject } from "@/shared/lib/di";
|
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import { useFilesStore } from "../store";
|
|
||||||
import type { FilesTableApiPort } from "./ports";
|
|
||||||
|
|
||||||
export const FILES_TABLE_API_PROVIDE_KEY =
|
|
||||||
defineInjectKey<FilesTableApiPort>("FilesTableApi");
|
|
||||||
|
|
||||||
export function useFilesTableStore() {
|
|
||||||
const api = validInject(FILES_TABLE_API_PROVIDE_KEY);
|
|
||||||
|
|
||||||
const filesStore = useFilesStore();
|
|
||||||
const { files } = storeToRefs(filesStore);
|
|
||||||
|
|
||||||
const loader = useLoader();
|
|
||||||
async function fetchMany() {
|
|
||||||
const files = await loader.wait(api.fetchMany({}));
|
|
||||||
filesStore.setFiles(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reactive({
|
|
||||||
loading: loader.loading,
|
|
||||||
files,
|
|
||||||
fetchMany,
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
import type { Entity } from "@/shared/lib/entity";
|
|
||||||
|
|
||||||
export interface AppFile extends Entity {
|
|
||||||
name: string;
|
|
||||||
createdAt: Date;
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export type { AppFile } from "./file";
|
|
|
@ -1,3 +0,0 @@
|
||||||
import type { FilesTableApiPort } from "./FilesTable";
|
|
||||||
|
|
||||||
export type FileApiPort = FilesTableApiPort;
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { defineStore } from "pinia";
|
|
||||||
import { ref } from "vue";
|
|
||||||
import type { AppFile } from "./domain";
|
|
||||||
|
|
||||||
export const useFilesStore = defineStore("files", () => {
|
|
||||||
const data = ref([] as AppFile[]);
|
|
||||||
|
|
||||||
function setFiles(files: AppFile[]): void {
|
|
||||||
data.value = files;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addFile(file: AppFile): void {
|
|
||||||
data.value.unshift(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
return { files: data, setFiles, addFile };
|
|
||||||
});
|
|
|
@ -1,35 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, defineEmits } from "vue";
|
|
||||||
import { useListFormStore } from "./store";
|
|
||||||
import type { CreateListData } from "@/app_core/ports/list";
|
|
||||||
|
|
||||||
const emit = defineEmits(["submitForm"]);
|
|
||||||
|
|
||||||
const store = useListFormStore();
|
|
||||||
|
|
||||||
const listData = ref({
|
|
||||||
displayName: "",
|
|
||||||
} as CreateListData);
|
|
||||||
|
|
||||||
async function submitForm() {
|
|
||||||
await store.create(listData.value);
|
|
||||||
emit("submitForm");
|
|
||||||
listData.value = { displayName: "" };
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<label>Отображаемое имя</label>
|
|
||||||
<input v-model="listData.displayName" />
|
|
||||||
</div>
|
|
||||||
<BaseButton
|
|
||||||
:isPrimary="true"
|
|
||||||
:isLoading="store.loading"
|
|
||||||
@click="submitForm"
|
|
||||||
>
|
|
||||||
Добавить
|
|
||||||
</BaseButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,3 +0,0 @@
|
||||||
export { default as AudienceListForm } from "./AudienceListForm.vue";
|
|
||||||
export * from "./ports";
|
|
||||||
export { LIST_FORM_API_PROVIDE_KEY } from "./store";
|
|
|
@ -1,8 +0,0 @@
|
||||||
import type { BaseCreateApiPort } from "@/shared/lib/ports";
|
|
||||||
import type { List } from "../domain";
|
|
||||||
|
|
||||||
export interface ListFormApiCreateProps {
|
|
||||||
displayName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ListFormApiPort = BaseCreateApiPort<List, ListFormApiCreateProps>;
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { useLoader } from "@/shared/lib/composables/loader";
|
|
||||||
import { defineInjectKey, validInject } from "@/shared/lib/di";
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import { useListsStore } from "../store";
|
|
||||||
import type { ListFormApiCreateProps, ListFormApiPort } from "./ports";
|
|
||||||
|
|
||||||
export const LIST_FORM_API_PROVIDE_KEY =
|
|
||||||
defineInjectKey<ListFormApiPort>("ListFormApi");
|
|
||||||
|
|
||||||
export function useListFormStore() {
|
|
||||||
const api = validInject(LIST_FORM_API_PROVIDE_KEY);
|
|
||||||
|
|
||||||
const listsStore = useListsStore();
|
|
||||||
|
|
||||||
const loader = useLoader();
|
|
||||||
async function create(data: ListFormApiCreateProps) {
|
|
||||||
const list = await loader.wait(api.create(data));
|
|
||||||
listsStore.addList(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reactive({
|
|
||||||
loading: loader.loading,
|
|
||||||
create,
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from "vue";
|
|
||||||
import { useListsTableStore } from "./store";
|
|
||||||
|
|
||||||
const store = useListsTableStore();
|
|
||||||
|
|
||||||
const columns = computed(() => [{ key: "displayName", title: "Название" }]);
|
|
||||||
|
|
||||||
store.fetchMany();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<BaseTable
|
|
||||||
:loading="store.loading"
|
|
||||||
:columns="columns"
|
|
||||||
:dataItems="store.lists"
|
|
||||||
>
|
|
||||||
<template #displayName="{ dataItem }">
|
|
||||||
<RouterLink
|
|
||||||
:to="{ name: 'audience_contacts', params: { listId: dataItem.id } }"
|
|
||||||
>
|
|
||||||
{{ dataItem.displayName }}
|
|
||||||
</RouterLink>
|
|
||||||
</template>
|
|
||||||
</BaseTable>
|
|
||||||
</template>
|
|
|
@ -1,3 +0,0 @@
|
||||||
export { default as AudienceListsTable } from "./AudienceListsTable.vue";
|
|
||||||
export * from "./ports";
|
|
||||||
export { LISTS_TABLE_API_PROVIDE_KEY } from "./store";
|
|
|
@ -1,4 +0,0 @@
|
||||||
import type { BaseFetchManyApiPort } from "@/shared/lib/ports";
|
|
||||||
import type { List } from "../domain";
|
|
||||||
|
|
||||||
export type ListsTableApiPort = BaseFetchManyApiPort<List>;
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { useLoader } from "@/shared/lib/composables/loader";
|
|
||||||
import { defineInjectKey, validInject } from "@/shared/lib/di";
|
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
import { reactive } from "vue";
|
|
||||||
import { useListsStore } from "../store";
|
|
||||||
import type { ListsTableApiPort } from "./ports";
|
|
||||||
|
|
||||||
export const LISTS_TABLE_API_PROVIDE_KEY =
|
|
||||||
defineInjectKey<ListsTableApiPort>("ListsTableApi");
|
|
||||||
|
|
||||||
export function useListsTableStore() {
|
|
||||||
const api = validInject(LISTS_TABLE_API_PROVIDE_KEY);
|
|
||||||
|
|
||||||
const listsStore = useListsStore();
|
|
||||||
const { lists } = storeToRefs(listsStore);
|
|
||||||
|
|
||||||
const loader = useLoader();
|
|
||||||
async function fetchMany() {
|
|
||||||
const lists = await loader.wait(api.fetchMany({}));
|
|
||||||
listsStore.setLists(lists);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reactive({
|
|
||||||
loading: loader.loading,
|
|
||||||
lists,
|
|
||||||
fetchMany,
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,8 +1,3 @@
|
||||||
import type { ListsTableApiPort } from "./ListsTable";
|
|
||||||
import type { ListsSelectApiPort } from "./ListsSelect";
|
import type { ListsSelectApiPort } from "./ListsSelect";
|
||||||
import type { ListFormApiPort } from "./ListForm";
|
|
||||||
export type { ListFormApiCreateProps } from "./ListForm";
|
|
||||||
|
|
||||||
export type ListApiPort = ListsTableApiPort &
|
export type ListApiPort = ListsSelectApiPort;
|
||||||
ListsSelectApiPort &
|
|
||||||
ListFormApiPort;
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import type { FileApiPort } from "@/app/files";
|
|
||||||
import type { AppFile } from "@/app/files/domain";
|
|
||||||
import { delay } from "@/shared/lib/utils/promise";
|
|
||||||
import { faker } from "@faker-js/faker";
|
|
||||||
|
|
||||||
let $instance: FileApiPort | undefined;
|
|
||||||
|
|
||||||
export class MockFileApi implements FileApiPort {
|
|
||||||
#files: AppFile[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.#files = Array.from(new Array(20).keys()).map((_) => {
|
|
||||||
const id = faker.datatype.uuid();
|
|
||||||
const name = faker.system.fileName();
|
|
||||||
const createdAt = faker.date.birthdate();
|
|
||||||
return { id, name, createdAt };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static getInstance() {
|
|
||||||
if (!$instance) {
|
|
||||||
$instance = new MockFileApi();
|
|
||||||
}
|
|
||||||
return $instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchMany(): Promise<AppFile[]> {
|
|
||||||
await delay(1000);
|
|
||||||
return this.#files.concat();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ListApiPort, ListFormApiCreateProps } from "@/app/lists";
|
import type { ListApiPort } from "@/app/lists";
|
||||||
import type { List } from "@/app/lists/domain";
|
import type { List } from "@/app/lists/domain";
|
||||||
import { delay } from "@/shared/lib/utils/promise";
|
import { delay } from "@/shared/lib/utils/promise";
|
||||||
import { faker } from "@faker-js/faker";
|
import { faker } from "@faker-js/faker";
|
||||||
|
@ -23,17 +23,6 @@ export class MockListApi implements ListApiPort {
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(createListData: ListFormApiCreateProps): Promise<List> {
|
|
||||||
const list: List = {
|
|
||||||
id: faker.datatype.uuid(),
|
|
||||||
...createListData,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.#lists.unshift(list);
|
|
||||||
await delay(1000);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchMany(): Promise<List[]> {
|
async fetchMany(): Promise<List[]> {
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
return this.#lists.concat();
|
return this.#lists.concat();
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { provide } from "vue";
|
|
||||||
import {
|
|
||||||
FilesTable,
|
|
||||||
FILES_TABLE_API_PROVIDE_KEY,
|
|
||||||
} from "@/app/files/FilesTable";
|
|
||||||
import { useMeta } from "@/shared/lib/composables/meta";
|
|
||||||
import { MockFileApi } from "@/infra/api/file";
|
|
||||||
|
|
||||||
useMeta("Файлы | SM");
|
|
||||||
|
|
||||||
const fileApi = MockFileApi.getInstance();
|
|
||||||
provide(FILES_TABLE_API_PROVIDE_KEY, fileApi);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="container">
|
|
||||||
<BasePageHeader>
|
|
||||||
Файлы
|
|
||||||
<template #extra>
|
|
||||||
<BaseButton :isPrimary="true">Добавить файл</BaseButton>
|
|
||||||
</template>
|
|
||||||
</BasePageHeader>
|
|
||||||
<FilesTable />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,33 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { provide } from "vue";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import {
|
|
||||||
AudienceListForm,
|
|
||||||
LIST_FORM_API_PROVIDE_KEY,
|
|
||||||
} from "@/app/lists/ListForm";
|
|
||||||
import { useMeta } from "@/shared/lib/composables/meta";
|
|
||||||
import { MockListApi } from "@/infra/api/list";
|
|
||||||
|
|
||||||
useMeta("Создание списка | Аудитория | SM");
|
|
||||||
|
|
||||||
const listApi = MockListApi.getInstance();
|
|
||||||
provide(LIST_FORM_API_PROVIDE_KEY, listApi);
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
function redirectToLists() {
|
|
||||||
router.push({ name: "audience_lists" });
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="container">
|
|
||||||
<BasePageHeader>
|
|
||||||
Создание списка
|
|
||||||
<template #extra>
|
|
||||||
<BaseButton @click="redirectToLists">Отменить</BaseButton>
|
|
||||||
</template>
|
|
||||||
</BasePageHeader>
|
|
||||||
<AudienceListForm @submitForm="redirectToLists" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { provide } from "vue";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import {
|
|
||||||
AudienceListsTable,
|
|
||||||
LISTS_TABLE_API_PROVIDE_KEY,
|
|
||||||
} from "@/app/lists/ListsTable";
|
|
||||||
import { useMeta } from "@/shared/lib/composables/meta";
|
|
||||||
import { MockListApi } from "@/infra/api/list";
|
|
||||||
|
|
||||||
useMeta("Списки | Аудитория | SM");
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
function openAddListForm() {
|
|
||||||
router.push({ name: "audience_create_list" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const listsApi = MockListApi.getInstance();
|
|
||||||
provide(LISTS_TABLE_API_PROVIDE_KEY, listsApi);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="container">
|
|
||||||
<BasePageHeader>
|
|
||||||
Списки
|
|
||||||
<template #extra>
|
|
||||||
<BaseButton :isPrimary="true" @click="openAddListForm">
|
|
||||||
Добавить список
|
|
||||||
</BaseButton>
|
|
||||||
</template>
|
|
||||||
</BasePageHeader>
|
|
||||||
<AudienceListsTable />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<script>
|
|
||||||
import { useMeta } from "@/shared/lib/composables/meta";
|
|
||||||
useMeta("Аудитория | SM");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="container">
|
|
||||||
<BaseNav>
|
|
||||||
<RouterLink :to="{ name: 'audience_contacts' }">Контакты</RouterLink>
|
|
||||||
<RouterLink :to="{ name: 'audience_lists' }">Списки</RouterLink>
|
|
||||||
</BaseNav>
|
|
||||||
</div>
|
|
||||||
<RouterView />
|
|
||||||
</template>
|
|
|
@ -53,7 +53,6 @@ provide(LISTS_SELECT_API_PROVIDE_KEY, listApi);
|
||||||
Контакты
|
Контакты
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<BaseButton @click="openAddContactForm">Добавить контакт</BaseButton>
|
<BaseButton @click="openAddContactForm">Добавить контакт</BaseButton>
|
||||||
<BaseButton :isPrimary="true">Импортировать контакты</BaseButton>
|
|
||||||
</template>
|
</template>
|
||||||
</BasePageHeader>
|
</BasePageHeader>
|
||||||
<AudienceListsSelect
|
<AudienceListsSelect
|
|
@ -1,31 +1,13 @@
|
||||||
const audienceRoutes = [
|
const audienceRoutes = [
|
||||||
{
|
{
|
||||||
path: "/audience",
|
path: "/contacts/new",
|
||||||
name: "audience",
|
name: "audience_create_contact",
|
||||||
redirect: { name: "audience_contacts" },
|
component: () => import("./CreateContactPage.vue"),
|
||||||
component: () => import("./AudiencePage.vue"),
|
},
|
||||||
children: [
|
{
|
||||||
{
|
path: "/contacts/:listId?",
|
||||||
path: "contacts/new",
|
name: "audience_contacts",
|
||||||
name: "audience_create_contact",
|
component: () => import("./ContactsPage.vue"),
|
||||||
component: () => import("./AudienceCreateContactPage.vue"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "contacts/:listId?",
|
|
||||||
name: "audience_contacts",
|
|
||||||
component: () => import("./AudienceContactsPage.vue"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "lists/new",
|
|
||||||
name: "audience_create_list",
|
|
||||||
component: () => import("./AudienceCreateListPage.vue"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "lists",
|
|
||||||
name: "audience_lists",
|
|
||||||
component: () => import("./AudienceListsPage.vue"),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,6 @@ const router = createRouter({
|
||||||
redirect: { name: "audience" },
|
redirect: { name: "audience" },
|
||||||
},
|
},
|
||||||
...audienceRoutes,
|
...audienceRoutes,
|
||||||
{
|
|
||||||
path: "/files",
|
|
||||||
name: "email_files",
|
|
||||||
component: () => import("./FilesPage.vue"),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/:pathMatch(.*)*",
|
path: "/:pathMatch(.*)*",
|
||||||
name: "not_found",
|
name: "not_found",
|
||||||
|
|
Loading…
Reference in a new issue