made link to entity optional

Signed-off-by: Lykke Axlin <lykkeaxlin@hotmail.com>

Co-authored-by: klaraab <klarabroman@live.se>
This commit is contained in:
Lykke Axlin
2021-12-13 15:45:52 +01:00
parent 86db169be1
commit ad86729f5d
45 changed files with 1973 additions and 1050 deletions
@@ -0,0 +1,171 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
exports.up = async function up(knex) {
if (knex.client.config.client === 'sqlite3') {
await knex.schema.dropTable('metadata');
await knex.schema.createTable('metadata', table => {
table.increments('id').comment('Automatically generated unique ID');
table.text('entity_ref').unique().comment('The ref of the entity');
table.text('name').notNullable().comment('The name of the entity');
table
.text('community')
.comment('Link to where the community can discuss ideas');
table
.text('description')
.notNullable()
.comment('The description of the Bazaar project');
table
.text('status')
.defaultTo('proposed')
.notNullable()
.comment('The status of the Bazaar project');
table
.text('updated_at')
.notNullable()
.comment('Timestamp on ISO 8601 format when entity was last updated');
table
.text('size')
.defaultTo('medium')
.notNullable()
.comment('The estimated magnitude of the project');
table
.text('start_date')
.comment('Optional start date of the project (ISO 8601 format)');
table
.text('end_date')
.comment('Optional end date of the project (ISO 8601 format)');
table
.text('responsible')
.notNullable()
.comment('Contact person of the project');
});
await knex.schema.dropTable('members');
await knex.schema.createTable('members', table => {
table
.integer('item_id')
.references('metadata.id')
.onDelete('CASCADE')
.comment('Id of the associated item');
table
.text('entity_ref')
.references('metadata.entity_ref')
.onDelete('CASCADE')
.comment('The ref of the entity');
table.text('user_id').notNullable().comment('The user id of the member');
table
.dateTime('join_date')
.defaultTo(knex.fn.now())
.notNullable()
.comment('The timestamp when this member joined');
table.text('picture').comment('Link to profile picture');
});
} else {
await knex.schema.alterTable('metadata', table => {
table.renameColumn('announcement', 'description');
table.increments('id').comment('Automatically generated unique ID');
table.string('entity_ref').nullable().alter();
});
await knex.schema.alterTable('members', table => {
table
.integer('item_id')
.references('metadata.id')
.onDelete('CASCADE')
.comment('Id of the associated item');
table.dropColumn('entity_ref');
});
}
};
exports.down = async function down(knex) {
if (knex.client.config.client === 'sqlite3') {
await knex.schema.dropTable('metadata');
await knex.schema.createTable('metadata', table => {
table
.text('entity_ref')
.notNullable()
.unique()
.comment('The ref of the entity');
table.text('name').notNullable().comment('The name of the entity');
table
.text('community')
.comment('Link to where the community can discuss ideas');
table
.text('announcement')
.notNullable()
.comment('The announcement of the Bazaar project');
table
.text('status')
.defaultTo('proposed')
.notNullable()
.comment('The status of the Bazaar project');
table
.text('updated_at')
.notNullable()
.comment('Timestamp on ISO 8601 format when entity was last updated');
table
.text('size')
.defaultTo('medium')
.notNullable()
.comment('The estimated magnitude of the project');
table
.text('start_date')
.comment('Optional start date of the project (ISO 8601 format)');
table
.text('end_date')
.comment('Optional end date of the project (ISO 8601 format)');
table
.text('responsible')
.notNullable()
.comment('Contact person of the project');
});
await knex.schema.dropTable('members');
await knex.schema.createTable('members', table => {
table
.text('entity_ref')
.notNullable()
.references('metadata.entity_ref')
.onDelete('CASCADE')
.comment('The ref of the entity');
table.text('user_id').notNullable().comment('The user id of the member');
table
.dateTime('join_date')
.defaultTo(knex.fn.now())
.notNullable()
.comment('The timestamp when this member joined');
table.text('picture').comment('Link to profile picture');
});
} else {
await knex.schema.alterTable('metadata', table => {
table.renameColumn('description', 'announcement');
table.string('entity_ref').notNullable().alter();
table.dropColumn('id');
});
await knex.schema.alterTable('members', table => {
table.dropColumn('item_id');
table
.text('entity_ref')
.notNullable()
.references('metadata.entity_ref')
.onDelete('CASCADE')
.comment('The ref of the entity');
});
}
};
@@ -22,7 +22,7 @@ const bazaarProject: any = {
entityRef: 'ref1',
community: '',
status: 'proposed',
announcement: 'a',
description: 'a',
membersCount: 0,
startDate: '2021-11-07T13:27:00.000Z',
endDate: null,
@@ -50,7 +50,7 @@ describe('DatabaseHandler', () => {
await knex('metadata').insert({
entity_ref: bazaarProject.entityRef,
name: bazaarProject.name,
announcement: bazaarProject.announcement,
description: bazaarProject.description,
community: bazaarProject.community,
status: bazaarProject.status,
updated_at: new Date().toISOString(),
@@ -60,10 +60,10 @@ describe('DatabaseHandler', () => {
responsible: bazaarProject.responsible,
});
const res = await dbHandler.getMetadata('ref1');
const res = await dbHandler.getMetadataByRef('ref1');
expect(res).toHaveLength(1);
expect(res[0].announcement).toEqual('a');
expect(res[0].description).toEqual('a');
expect(res[0].community).toEqual('');
expect(res[0].status).toEqual('proposed');
expect(res[0].start_date).toEqual('2021-11-07T13:27:00.000Z');
@@ -44,10 +44,10 @@ export class DatabaseHandler {
}
private columns = [
'members.entity_ref',
'metadata.id',
'metadata.entity_ref',
'metadata.name',
'metadata.announcement',
'metadata.description',
'metadata.status',
'metadata.updated_at',
'metadata.community',
@@ -57,40 +57,52 @@ export class DatabaseHandler {
'metadata.responsible',
];
async getMembers(entityRef: string) {
async getMembers(id: string) {
return await this.database
.select('*')
.from('members')
.where({ entity_ref: entityRef });
.where({ item_id: id });
}
async addMember(userId: string, entityRef: string, picture?: string) {
async addMember(id: number, userId: string, picture?: string) {
await this.database
.insert({
entity_ref: entityRef,
item_id: id,
user_id: userId,
picture: picture,
})
.into('members');
}
async deleteMember(userId: string, entityRef: string) {
async deleteMember(id: number, userId: string) {
return await this.database('members')
.where({ entity_ref: decodeURIComponent(entityRef) })
.where({ item_id: id })
.andWhere('user_id', userId)
.del();
}
async getMetadata(entityRef: string) {
async getMetadataById(id: number) {
const coalesce = this.database.raw(
'coalesce(count(members.entity_ref), 0) as members_count',
'coalesce(count(members.item_id), 0) as members_count',
);
return await this.database('metadata')
.select([...this.columns, coalesce])
.where({ 'metadata.id': id })
.groupBy(this.columns)
.leftJoin('members', 'metadata.id', '=', 'members.item_id');
}
async getMetadataByRef(entityRef: string) {
const coalesce = this.database.raw(
'coalesce(count(members.item_id), 0) as members_count',
);
return await this.database('metadata')
.select([...this.columns, coalesce])
.where({ 'metadata.entity_ref': entityRef })
.groupBy(this.columns)
.leftJoin('members', 'metadata.entity_ref', '=', 'members.entity_ref');
.leftJoin('members', 'metadata.id', '=', 'members.item_id');
}
async insertMetadata(bazaarProject: any) {
@@ -98,7 +110,7 @@ export class DatabaseHandler {
name,
entityRef,
community,
announcement,
description,
status,
size,
startDate,
@@ -108,11 +120,11 @@ export class DatabaseHandler {
await this.database
.insert({
name: name,
name,
entity_ref: entityRef,
community: community,
announcement: announcement,
status: status,
community,
description,
status,
updated_at: new Date().toISOString(),
size,
start_date: startDate,
@@ -124,9 +136,11 @@ export class DatabaseHandler {
async updateMetadata(bazaarProject: any) {
const {
name,
id,
entityRef,
community,
announcement,
description,
status,
size,
startDate,
@@ -134,34 +148,32 @@ export class DatabaseHandler {
responsible,
} = bazaarProject;
return await this.database('metadata')
.where({ entity_ref: entityRef })
.update({
announcement: announcement,
community: community,
status: status,
updated_at: new Date().toISOString(),
size,
start_date: startDate,
end_date: endDate,
responsible,
});
return await this.database('metadata').where({ id: id }).update({
name,
entity_ref: entityRef,
description,
community,
status,
updated_at: new Date().toISOString(),
size,
start_date: startDate,
end_date: endDate,
responsible,
});
}
async deleteMetadata(entityRef: string) {
return await this.database('metadata')
.where({ entity_ref: entityRef })
.del();
async deleteMetadata(id: number) {
return await this.database('metadata').where({ id: id }).del();
}
async getEntities() {
async getProjects() {
const coalesce = this.database.raw(
'coalesce(count(members.entity_ref), 0) as members_count',
'coalesce(count(members.item_id), 0) as members_count',
);
return await this.database('metadata')
.select([...this.columns, coalesce])
.groupBy(this.columns)
.leftJoin('members', 'metadata.entity_ref', '=', 'members.entity_ref');
.leftJoin('members', 'metadata.id', '=', 'members.item_id');
}
}
+33 -22
View File
@@ -40,28 +40,27 @@ export async function createRouter(
const router = Router();
router.use(express.json());
router.get('/members/:ref', async (request, response) => {
const entity_ref = decodeURIComponent(request.params.ref);
const data = await dbHandler.getMembers(entity_ref);
router.get('/projects/:id/members', async (request, response) => {
const members = await dbHandler.getMembers(request.params.id);
if (data?.length) {
response.json({ status: 'ok', data: data });
if (members?.length) {
response.json({ status: 'ok', data: members });
} else {
response.json({ status: 'ok', data: [] });
}
});
router.put('/member', async (request, response) => {
const { user_id, entity_ref, picture } = request.body;
await dbHandler.addMember(user_id, entity_ref, picture);
router.put('/projects/:id/member/:userId', async (request, response) => {
const { id, userId } = request.params;
await dbHandler.addMember(parseInt(id, 10), userId, request.body?.picture);
response.json({ status: 'ok' });
});
router.delete('/member/:ref/:id', async (request, response) => {
const { ref, id } = request.params;
router.delete('/projects/:id/member/:userId', async (request, response) => {
const { id, userId } = request.params;
const count = await dbHandler.deleteMember(id, ref);
const count = await dbHandler.deleteMember(parseInt(id, 10), userId);
if (count) {
response.json({ status: 'ok' });
@@ -70,36 +69,48 @@ export async function createRouter(
}
});
router.get('/metadata/:ref', async (request, response) => {
router.get('/projects/id/:id', async (request, response) => {
const id = decodeURIComponent(request.params.id);
const data = await dbHandler.getMetadataById(parseInt(id, 10));
response.json({ status: 'ok', data: data });
});
router.get('/projects/ref/:ref', async (request, response) => {
const ref = decodeURIComponent(request.params.ref);
const data = await dbHandler.getMetadata(ref);
const data = await dbHandler.getMetadataByRef(ref);
response.json({ status: 'ok', data: data });
});
router.get('/entities', async (_, response) => {
const data = await dbHandler.getEntities();
router.get('/projects', async (_, response) => {
const data = await dbHandler.getProjects();
response.json({ status: 'ok', data: data });
});
router.put('/metadata', async (request, response) => {
router.put('/projects', async (request, response) => {
const bazaarProject = request.body;
const count = await dbHandler.updateMetadata(bazaarProject);
if (count) {
response.json({ status: 'ok' });
} else {
await dbHandler.insertMetadata(bazaarProject);
response.json({ status: 'ok' });
}
});
router.delete('/metadata/:ref', async (request, response) => {
const ref = decodeURIComponent(request.params.ref);
router.post('/projects', async (request, response) => {
const bazaarProject = request.body;
const count = await dbHandler.deleteMetadata(ref);
await dbHandler.insertMetadata(bazaarProject);
response.json({ status: 'ok' });
});
router.delete('/projects/:id', async (request, response) => {
const id = decodeURIComponent(request.params.id);
const count = await dbHandler.deleteMetadata(parseInt(id, 10));
if (count) {
response.json({ status: 'ok' });