Browse Source

lavori in corso sull'aggancio alle api di insermento, modifica e cancellazione delle relazioni

pull/1384/head
mauro 4 years ago
parent
commit
d326059f53
9 changed files with 89 additions and 49 deletions
  1. 6
      .gitignore
  2. 2
      frontend/components/tasks/sequenceLabeling/EntityItem.vue
  3. 8
      frontend/components/tasks/sequenceLabeling/EntityItemBox.vue
  4. 14
      frontend/domain/models/links/link.ts
  5. 8
      frontend/domain/models/links/linkRepository.ts
  6. 27
      frontend/pages/projects/_id/sequence-labeling/index.vue
  7. 53
      frontend/repositories/links/apiLinkRepository.ts
  8. 12
      frontend/services/application/tasks/sequenceLabeling/sequenceLabelingApplicationService.ts
  9. 8
      frontend/store/auth.js

6
.gitignore

@ -201,3 +201,9 @@ bundle/
webpack-stats.json
.vscode
/app/doccano.db
/app/run.bat
/frontend/components/layout/doccano.json
/frontend/package-lock.json
/frontend/run.bat
/run-docker-dev.bat

2
frontend/components/tasks/sequenceLabeling/EntityItem.vue

@ -68,7 +68,7 @@
:key="i"
>
<v-list-item-content>
<v-list-item-subtitle v-text="link.targetName"></v-list-item-subtitle>
<v-list-item-subtitle v-text="link.targetLabel"></v-list-item-subtitle>
</v-list-item-content>
<v-list-item-action>

8
frontend/components/tasks/sequenceLabeling/EntityItemBox.vue

@ -184,7 +184,7 @@ export default {
color: label.backgroundColor,
text: piece,
selectedAsLinkSource: false,
links: []
links: [] // must use targetId to get target label (it's not stored)
})
}
// add the rest of text.
@ -211,19 +211,19 @@ export default {
this.chunks.forEach(function(fromChunk) {
if (fromChunk.links) {
fromChunk.links.forEach(function(toChunk) {
fromChunk.links.forEach(function(link) {
let childPos = document.getElementById('spn-' + fromChunk.id).getBoundingClientRect();
const x1 = (childPos.x + childPos.width / 2) - parentPos.x;
const y1 = (childPos.y + childPos.height / 2) - parentPos.y;
childPos = document.getElementById('spn-' + toChunk.id).getBoundingClientRect();
childPos = document.getElementById('spn-' + link.targetId).getBoundingClientRect();
const x2 = (childPos.x + childPos.width / 2) - parentPos.x;
const y2 = (childPos.y + childPos.height / 2) - parentPos.y;
ctx.beginPath();
ctx.lineWidth = 3;
ctx.moveTo(x1, y1);
ctx.strokeStyle = toChunk.color;
ctx.strokeStyle = link.color;
if (y1 === y2) {
ctx.lineTo(x1, y1 + 35);

14
frontend/domain/models/links/link.ts

@ -73,15 +73,17 @@ export class LinkItem {
public id: number,
public annotation_id_1: number,
public annotation_id_2: number,
public type: number
public type: number,
public user: number,
public timestamp: string
) {
}
static valueOf(
{id, annotation_id_1, annotation_id_2, type}:
{ id: number, annotation_id_1: number, annotation_id_2: number, type: number }
{id, annotation_id_1, annotation_id_2, type, user, timestamp}:
{ id: number, annotation_id_1: number, annotation_id_2: number, type: number, user:number, timestamp:string }
): LinkItem {
return new LinkItem(id, annotation_id_1, annotation_id_2, type)
return new LinkItem(id, annotation_id_1, annotation_id_2, type, user, timestamp)
}
toObject(): Object {
@ -89,7 +91,9 @@ export class LinkItem {
id: this.id,
annotation_id_1: this.annotation_id_1,
annotation_id_2: this.annotation_id_2,
type: this.type
type: this.type,
user: this.user,
timestamp: this.timestamp
}
}
}

8
frontend/domain/models/links/linkRepository.ts

@ -1,9 +1,9 @@
import { LinkItem } from '~/domain/models/links/link'
import {LinkItem} from '~/domain/models/links/link'
export interface LinkRepository {
create(projectId: string, link: LinkItem): Promise<LinkItem>
create(projectId: string, link: LinkItem): Promise<LinkItem>
update(projectId: string, link: LinkItem): Promise<LinkItem>
update(projectId: string, linkId: number, linkType: number): Promise<LinkItem>
bulkDelete(projectId: string, linkIds: number[]): Promise<void>
bulkDelete(projectId: string, linkIds: number[]): Promise<void>
}

27
frontend/pages/projects/_id/sequence-labeling/index.vue

@ -49,6 +49,7 @@
<script>
import _ from 'lodash'
import {mapGetters} from 'vuex'
import LayoutText from '@/components/tasks/layout/LayoutText'
import ListMetadata from '@/components/tasks/metadata/ListMetadata'
import ToolbarLaptop from '@/components/tasks/toolbar/ToolbarLaptop'
@ -101,6 +102,8 @@ export default {
},
computed: {
...mapGetters('auth', ['isAuthenticated', 'getUsername', 'getUserId']),
shortKeys() {
return Object.fromEntries(this.labels.map(item => [item.id, [item.suffixKey]]))
},
@ -183,14 +186,15 @@ export default {
selectTarget(chunk) {
// skips duplicated links
if (!chunk.links.find(ch => ch.id === this.sourceChunk.id)) {
// await this.$services.sequenceLabeling.createLink(this.projectId, this.doc.id, this.sourceChunk.id, chunk.id, this.sourceLinkType.id)
// await this.$services.sequenceLabeling.createLink(this.projectId, this.sourceChunk.id, chunk.id, this.sourceLinkType.id, this.getUserId)
// await this.list(this.doc.id)
this.sourceChunk.links.push({
id: chunk.id,
id: -1,
type: this.sourceLinkType.id,
color: this.sourceLinkType.color,
targetName: chunk.text
targetId: chunk.id,
targetLabel: chunk.text
});
}
this.hideAllLinkMenus();
@ -200,14 +204,21 @@ export default {
this.sourceLink = link;
},
deleteLink(id, ndx) {
this.sourceChunk.links.splice(ndx, 1);
this.sourceLink = NONE;
async deleteLink(id, ndx) {
await this.$services.sequenceLabeling.deleteLink(this.projectId, this.sourceChunk.links[ndx].id)
await this.list(this.doc.id)
// this.sourceChunk.links.splice(ndx, 1);
// this.sourceLink = NONE;
this.hideAllLinkMenus();
},
selectNewLinkType(type) {
this.sourceLinkType = type;
async selectNewLinkType(type) {
await this.$services.sequenceLabeling.updateLink(this.projectId, 0, this.sourceLinkType.id)
await this.list(this.doc.id)
// this.sourceLinkType = type;
},
changeLinkType(type) {

53
frontend/repositories/links/apiLinkRepository.ts

@ -1,35 +1,38 @@
import ApiService from '@/services/api.service'
import { LinkRepository } from "~/domain/models/links/linkRepository";
import { LinkItem } from "~/domain/models/links/link";
import {LinkRepository} from "~/domain/models/links/linkRepository";
import {LinkItem} from "~/domain/models/links/link";
export interface LinkResponse {
id: number
annotation_id_1: number
annotation_id_2: number
type: number
id: number
annotation_id_1: number
annotation_id_2: number
type: number,
user: number,
timestamp: string
}
export class ApiLinkRepository implements LinkRepository {
constructor(
private readonly request = ApiService
) {}
constructor(
private readonly request = ApiService
) {
}
async create(projectId: string, item: LinkItem): Promise<LinkItem> {
const url = `/projects/${projectId}/annotation_relations`
const response = await this.request.post(url, item.toObject())
const responseItem: LinkResponse = response.data
return LinkItem.valueOf(responseItem)
}
async create(projectId: string, item: LinkItem): Promise<LinkItem> {
const url = `/projects/${projectId}/annotation_relations`
const response = await this.request.post(url, item.toObject())
const responseItem: LinkResponse = response.data
return LinkItem.valueOf(responseItem)
}
async update(projectId: string, item: LinkItem): Promise<LinkItem> {
const url = `/projects/${projectId}/annotation_relations/${item.id}`
const response = await this.request.patch(url, item.toObject())
const responseItem: LinkResponse = response.data
return LinkItem.valueOf(responseItem)
}
async update(projectId: string, linkId: number, linkType: number): Promise<LinkItem> {
const url = `/projects/${projectId}/annotation_relations/${linkId}`
const response = await this.request.patch(url, {type: linkType})
const responseItem: LinkResponse = response.data
return LinkItem.valueOf(responseItem)
}
async bulkDelete(projectId: string, linkIds: number[]): Promise<void> {
const url = `/projects/${projectId}/annotation_relations`
await this.request.delete(url, { ids: linkIds })
}
async bulkDelete(projectId: string, linkIds: number[]): Promise<void> {
const url = `/projects/${projectId}/annotation_relations`
await this.request.delete(url, {ids: linkIds})
}
}

12
frontend/services/application/tasks/sequenceLabeling/sequenceLabelingApplicationService.ts

@ -27,8 +27,16 @@ export class SequenceLabelingApplicationService extends AnnotationApplicationSer
await this.repository.update(projectId, docId, annotationId, labelId)
}
public async createLink(projectId: string, docId: number, sourceId: number, targetId: number, linkType: number): Promise<void> {
const link = new LinkItem(0, sourceId, targetId, linkType);
public async createLink(projectId: string, sourceId: number, targetId: number, linkType: number, userId: number): Promise<void> {
const link = new LinkItem(0, sourceId, targetId, linkType, userId, (new Date()).toISOString());
await this.linkRepository.create(projectId, link);
}
public async deleteLink(projectId: string, linkId: number): Promise<void> {
await this.linkRepository.bulkDelete(projectId, [linkId]);
}
public async updateLink(projectId: string, linkId: number, linkType: number): Promise<void> {
await this.linkRepository.update(projectId, linkId, linkType);
}
}

8
frontend/store/auth.js

@ -1,5 +1,6 @@
export const state = () => ({
username: null,
id: null,
isAuthenticated: false
})
@ -7,6 +8,9 @@ export const mutations = {
setUsername(state, username) {
state.username = username
},
setUserId(state, userId) {
state.id = userId
},
clearUsername(state) {
state.username = null
},
@ -21,6 +25,9 @@ export const getters = {
},
getUsername(state) {
return state.username
},
getUserId(state) {
return state.id
}
}
@ -38,6 +45,7 @@ export const actions = {
const user = await this.$services.user.getMyProfile()
commit('setAuthenticated', true)
commit('setUsername', user.username)
commit('setUserId', user.id)
} catch {
commit('setAuthenticated', false)
}

Loading…
Cancel
Save