From 4efa48d1d33836c9c6ebf032238d49802331dabe Mon Sep 17 00:00:00 2001 From: paco Date: Tue, 1 Mar 2022 12:59:24 +0100 Subject: [PATCH] APLU / Arbo --- api/src/graphql/aplu.sdl.ts | 11 ++ api/src/lib/files/S3Path.test.ts | 5 + api/src/lib/files/S3Path.ts | 17 ++- api/src/services/aplu/aplu.scenarios.ts | 146 ++++++++++++++++++++++++ api/src/services/aplu/aplu.test.ts | 40 +++++++ api/src/services/aplu/aplu.ts | 42 +++++++ 6 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 api/src/graphql/aplu.sdl.ts create mode 100644 api/src/services/aplu/aplu.scenarios.ts create mode 100644 api/src/services/aplu/aplu.test.ts create mode 100644 api/src/services/aplu/aplu.ts diff --git a/api/src/graphql/aplu.sdl.ts b/api/src/graphql/aplu.sdl.ts new file mode 100644 index 0000000..58e7e67 --- /dev/null +++ b/api/src/graphql/aplu.sdl.ts @@ -0,0 +1,11 @@ +export const schema = gql` + type Query { + arbo: ArboPath! @requireAuth + } + + type ArboPath { + path: String! + count: Int! + children: [ArboPath!]! + } +` diff --git a/api/src/lib/files/S3Path.test.ts b/api/src/lib/files/S3Path.test.ts index 42482be..025da29 100644 --- a/api/src/lib/files/S3Path.test.ts +++ b/api/src/lib/files/S3Path.test.ts @@ -22,4 +22,9 @@ describe('paths', () => { expect(S3Path.getPath('a/b/', 'b.zip')).toEqual('a/b/b.zip') expect(S3Path.getPath('/', 'b.zip')).toEqual('b.zip') }) + it('splitPath', () => { + expect(S3Path.splitPath('a.jpg')).toEqual(['a.jpg']) + expect(S3Path.splitPath('a/b.jpg')).toEqual(['a', 'b.jpg']) + expect(S3Path.splitPath('a/b/c.jpg')).toEqual(['a', 'b', 'c.jpg']) + }) }) diff --git a/api/src/lib/files/S3Path.ts b/api/src/lib/files/S3Path.ts index 130e7f7..c5f2ebb 100644 --- a/api/src/lib/files/S3Path.ts +++ b/api/src/lib/files/S3Path.ts @@ -1,10 +1,7 @@ -export default { +const S3Path = { getBasePath(path: string) { - const basePath = path - .split('/') - .filter((p) => p !== '') - .slice(0, -1) - .join('/') + const splitted = S3Path.splitPath(path) + const basePath = splitted.slice(0, -1).join('/') return basePath }, @@ -29,4 +26,12 @@ export default { return path }, + + splitPath(path: string) { + const splitted = path.split('/').filter((p) => p !== '') + + return splitted + }, } + +export default S3Path diff --git a/api/src/services/aplu/aplu.scenarios.ts b/api/src/services/aplu/aplu.scenarios.ts new file mode 100644 index 0000000..ce89c4e --- /dev/null +++ b/api/src/services/aplu/aplu.scenarios.ts @@ -0,0 +1,146 @@ +export const standard = defineScenario({ + tagGroup: { + one: { + data: { + name: 'TG1', + }, + }, + two: { + data: { + name: 'TG2', + }, + }, + }, + tag: { + g1t1: (scenario) => ({ + data: { + name: 'g1t1', + tagGroupId: scenario.tagGroup.one.id, + }, + }), + g1t2: (scenario) => ({ + data: { + name: 'g1t2', + tagGroupId: scenario.tagGroup.one.id, + }, + }), + g1t3: (scenario) => ({ + data: { + name: 'g1t3', + tagGroupId: scenario.tagGroup.one.id, + }, + }), + g2t1: (scenario) => ({ + data: { + name: 'g2t1', + tagGroupId: scenario.tagGroup.two.id, + }, + }), + g2t2: (scenario) => ({ + data: { + name: 'g2t2', + tagGroupId: scenario.tagGroup.two.id, + }, + }), + g2t3: (scenario) => ({ + data: { + name: 'g2t3', + tagGroupId: scenario.tagGroup.two.id, + }, + }), + }, + + image: { + p1: (scenario) => ({ + data: { + path: 'p1.jpg', + dateTaken: '2022-01-01T00:01:00Z', + tagsOnImages: { + create: [ + { + tagId: scenario.tag.g1t1.id, + }, + { + tagId: scenario.tag.g2t1.id, + }, + ], + }, + }, + }), + p2: (scenario) => ({ + data: { + path: 'ath1/p2.jpg', + dateTaken: '2022-01-01T00:02:00Z', + tagsOnImages: { + create: [ + { + tagId: scenario.tag.g1t2.id, + }, + { + tagId: scenario.tag.g2t2.id, + }, + ], + }, + }, + }), + p3: (scenario) => ({ + data: { + path: 'ath1/ath2/p3.jpg', + dateTaken: '2022-01-01T00:03:00Z', + tagsOnImages: { + create: [ + { + tagId: scenario.tag.g1t1.id, + }, + { + tagId: scenario.tag.g2t2.id, + }, + ], + }, + }, + }), + p4: (scenario) => ({ + data: { + path: 'ath3/p4.jpg', + dateTaken: '2022-01-01T00:04:00Z', + tagsOnImages: { + create: [ + { + tagId: scenario.tag.g1t2.id, + }, + { + tagId: scenario.tag.g2t1.id, + }, + ], + }, + }, + }), + p5: (scenario) => ({ + data: { + path: 'p5.jpg', + dateTaken: '2022-01-01T00:05:00Z', + tagsOnImages: { + create: [ + { + tagId: scenario.tag.g1t1.id, + }, + { + tagId: scenario.tag.g2t2.id, + }, + { + tagId: scenario.tag.g2t3.id, + }, + ], + }, + }, + }), + notag: { + data: { + path: 'notag.jpg', + dateTaken: '2022-01-02T00:00:00Z', + }, + }, + }, +}) + +export type StandardScenario = typeof standard diff --git a/api/src/services/aplu/aplu.test.ts b/api/src/services/aplu/aplu.test.ts new file mode 100644 index 0000000..4cc40ea --- /dev/null +++ b/api/src/services/aplu/aplu.test.ts @@ -0,0 +1,40 @@ +import { arbo } from './aplu' +import { ArboPath } from 'types/graphql' + +type NewArbo = { + path: string + count: number + children: Record +} + +function arboToObject(arbo: ArboPath): NewArbo { + return { + path: arbo.path, + count: arbo.count, + children: arbo.children.reduce( + (acc, curr) => ({ + ...acc, + [curr.path]: arboToObject(curr), + }), + {} + ), + } +} + +describe('aplu', () => { + scenario('arbo', async (scenario) => { + const root = await arbo() + const rootO = arboToObject(root) + expect(rootO.path).toBe('/') + expect(rootO.count).toEqual(Object.keys(scenario.image).length) + expect(Object.keys(rootO.children).length).toEqual(2) + + expect(rootO.children.ath1.path).toEqual('ath1') + expect(rootO.children.ath1.count).toEqual(2) + expect(Object.keys(rootO.children.ath1.children).length).toEqual(1) + expect(rootO.children.ath1.children.ath2.path).toEqual('ath2') + expect(rootO.children.ath1.children.ath2.count).toEqual(1) + expect(rootO.children.ath3.path).toEqual('ath3') + expect(rootO.children.ath3.count).toEqual(1) + }) +}) diff --git a/api/src/services/aplu/aplu.ts b/api/src/services/aplu/aplu.ts new file mode 100644 index 0000000..8fe0dbd --- /dev/null +++ b/api/src/services/aplu/aplu.ts @@ -0,0 +1,42 @@ +import type { ArboPath } from 'types/graphql' +import { db } from 'src/lib/db' +import _ from 'lodash' +import S3Path from 'src/lib/files/S3Path' + +export const arbo = async (): Promise => { + const root = { + path: '/', + count: 0, + children: [], + } + + const allImages = await db.image.findMany({ + select: { + path: true, + }, + }) + root.count = allImages.length + + _.forEach(allImages, ({ path }) => { + const basePath = S3Path.getBasePath(path) + const splitted = S3Path.splitPath(basePath) + + let currArbo = root + if (splitted.length === 0) return + + _.forEach(splitted, (subPath, i) => { + let subArbo = currArbo.children.find((a) => a.path === subPath) + if (!subArbo) { + subArbo = { + path: subPath, + count: 0, + children: [], + } + currArbo.children.push(subArbo) + } + currArbo = subArbo + currArbo.count++ + }) + }) + return root +}