Skip to content

Commit

Permalink
[RD-182] Persona 1 may add multiple authors to a copyright application
Browse files Browse the repository at this point in the history
 - Reduced the number of times the UI is generating access tokens
 - Simplified sub-forms; removed unnecesary field declarations
 - Saving numbers is still an issue: vuejs/vue#7136
 - TODO: Find a way to save integers by preventing them from being saved as strings
  • Loading branch information
lipsotiko authored and James Isaacs committed Mar 13, 2020
1 parent 11ed2b9 commit 89dec36
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 433 deletions.
42 changes: 27 additions & 15 deletions app/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
from werkzeug.utils import secure_filename

from app import app
from app.models import CopyrightApplication
from app.models import Author, CopyrightApplication
from . import appbuilder


def get_user():
return g.user


class CopyrightApplicationModelApi(ModelRestApi):
class CopyrightApplicationApi(ModelRestApi):
resource_name = 'copyright_application'
datamodel = SQLAInterface(CopyrightApplication)
base_filters = [['created_by', FilterEqualFunction, get_user]]
Expand All @@ -33,18 +33,7 @@ class CopyrightApplicationModelApi(ModelRestApi):
'year_completed',
'publication_date',
'publication_country',
'author_prefix',
'author_first_name',
'author_middle_name',
'author_last_name',
'author_suffix',
'author_pseudonym',
'author_citizenship',
'author_year_of_birth',
'author_year_of_death',
'author_organization',
'author_organization_name',
'domicile',
'authors',
'claimant_organization',
'claimant_organization_name',
'claimant_prefix',
Expand Down Expand Up @@ -81,7 +70,30 @@ class CopyrightApplicationModelApi(ModelRestApi):
]


appbuilder.add_api(CopyrightApplicationModelApi)
appbuilder.add_api(CopyrightApplicationApi)


class AuthorApi(ModelRestApi):
resource_name = 'author'
datamodel = SQLAInterface(Author)
add_columns = [
'copyright_application_id',
'prefix',
'first_name',
'middle_name',
'last_name',
'suffix',
'pseudonym',
'citizenship',
'year_of_birth',
'year_of_death',
'organization',
'organization_name',
'domicile'
]


appbuilder.add_api(AuthorApi)


class CurrentUserApi(BaseApi):
Expand Down
53 changes: 40 additions & 13 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@

from flask_appbuilder import Model
from flask_appbuilder.models.mixins import AuditMixin
from sqlalchemy import Boolean, Column, Integer, String
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Table
from sqlalchemy.orm import relationship

date_today = datetime.date.today()

assoc_copyright_application_author = Table(
'copyright_application_author',
Model.metadata,
Column('id', Integer, primary_key=True),
Column(
'copyright_application_id',
Integer,
ForeignKey('copyright_application.id')
),
Column('author_id', Integer, ForeignKey('author.id'))
)


class CopyrightApplication(AuditMixin, Model):
id = Column(Integer, primary_key=True)
Expand All @@ -14,18 +27,11 @@ class CopyrightApplication(AuditMixin, Model):
year_completed = Column(Integer)
publication_date = Column(String(8))
publication_country = Column(String(255))
author_prefix = Column(String(255))
author_first_name = Column(String(255))
author_middle_name = Column(String(255))
author_last_name = Column(String(255))
author_suffix = Column(String(255))
author_pseudonym = Column(String(255))
author_citizenship = Column(String(255))
author_year_of_birth = Column(Integer)
author_year_of_death = Column(Integer)
author_organization = Column(Boolean)
author_organization_name = Column(String(255))
domicile = Column(String(255))
authors = relationship(
'Author',
secondary=assoc_copyright_application_author,
backref='CopyrightApplication'
)
claimant_organization = Column(Boolean)
claimant_organization_name = Column(String(255))
claimant_prefix = Column(String(255))
Expand Down Expand Up @@ -70,3 +76,24 @@ def month_year(self):
def year(self):
date = self.created_on
return datetime.datetime(date.year, 1, 1)


class Author(Model):
id = Column(Integer, primary_key=True)
copyright_application_id = Column(
Integer,
ForeignKey('copyright_application.id'), nullable=False
)
copyright_application = relationship("CopyrightApplication")
prefix = Column(String(255))
first_name = Column(String(255))
middle_name = Column(String(255))
last_name = Column(String(255))
suffix = Column(String(255))
pseudonym = Column(String(255))
citizenship = Column(String(255))
year_of_birth = Column(Integer)
year_of_death = Column(Integer)
organization = Column(Boolean)
organization_name = Column(String(255))
domicile = Column(String(255))
13 changes: 1 addition & 12 deletions app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,7 @@ class CopyrightApplicationModelView(ModelView):
"year_completed",
"publication_date",
"publication_country",
"author_prefix",
"author_first_name",
"author_middle_name",
"author_last_name",
"author_suffix",
"author_pseudonym",
"author_citizenship",
"author_year_of_birth",
"author_year_of_death",
"author_organization",
"author_organization_name",
"domicile",
"authors",
"claimant_organization",
"claimant_organization_name",
"claimant_prefix",
Expand Down
4 changes: 2 additions & 2 deletions client/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ export default {
errorMessage: null
}),
async created () {
let accessToken = await this.repository._getAccessToken()
let currentUserInfo = await this.repository._getCurrentUserInfo(accessToken)
await this.repository._getAccessToken()
let currentUserInfo = await this.repository._getCurrentUserInfo()
if (!currentUserInfo) {
this.message = 'Please log in.'
} else if (!currentUserInfo.error) {
Expand Down
9 changes: 9 additions & 0 deletions client/src/style/general.scss
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,13 @@ summary {

summary::-webkit-details-marker {
display: none
}

.question-and-answer {
display: flex;
}

.question {
margin-top: 20px;
margin-right: 22px;
}
83 changes: 49 additions & 34 deletions client/src/utils/Repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ const axios = require('axios')

export default class Repository {
async _getCopyrightApplications (pageSize, page, applicationStatus) {
const accessToken = await this._getAccessToken()
const fields = ['primary_title', 'created_on', 'created_by', 'application_status', 'service_request_id'].join()
let filter = ''
if (applicationStatus !== 'all') { filter = ',filters:!((col:application_status,opr:eq,value:' + applicationStatus + '))' }
Expand All @@ -14,7 +13,7 @@ export default class Repository {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: accessToken
Authorization: localStorage.accessToken
}
}).catch(error => this.handleError(error))

Expand All @@ -29,43 +28,69 @@ export default class Repository {
}

async _saveCopyrightApplication (copyrightApplication) {
const baseUrl = '/api/v1/copyright_application/'
const id = copyrightApplication.id
await this._saveAuthors(copyrightApplication.id, copyrightApplication.authors)
const tmpCopyrightApplication = { ...copyrightApplication }
tmpCopyrightApplication.authors = copyrightApplication.authors.map(a => a.id)
return this.saveRequest('/api/v1/copyright_application/', tmpCopyrightApplication)
}

async _saveAuthor (copyrightApplicationId, author) {
author.copyrightApplicationId = copyrightApplicationId
return this.saveRequest('/api/v1/author/', author)
}

async _saveAuthors (copyrightApplicationId, authors) {
Promise.all(
authors.map(async a => {
return this._saveAuthor(copyrightApplicationId, a)
})
)
}

async saveRequest (baseUrl, entity) {
const id = entity.id
const url = (id) ? baseUrl + id : baseUrl
const method = (id) ? 'PUT' : 'POST'
const accessToken = await this._getAccessToken()
const translatedCopyrightApplication = keysToSnake(copyrightApplication)
const response = await axios({
url,
method,
headers: {
'Content-Type': 'application/json',
Authorization: accessToken
Authorization: localStorage.accessToken
},
data: {
...translatedCopyrightApplication
...keysToSnake(entity)

}
}).then(resp => {
if (id) {
return { ...resp.data.result, id }
} else {
return { ...resp.data.result, id: resp.data.id }
}
}).catch(error => this.handleError(error))

return keysToCamel(response.data)
return keysToCamel(response)
}

async _getCopyrightApplication (id) {
const accessToken = await this._getAccessToken()
const copyrightApplicationResponse = await axios({
url: '/api/v1/copyright_application/' + id,
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: accessToken
Authorization: localStorage.accessToken
}
}).catch(error => this.handleError(error))

let result
if (copyrightApplicationResponse.error) {
result = copyrightApplicationResponse
} else {
result = copyrightApplicationResponse.data.result
result = {
...copyrightApplicationResponse.data.result,
id: copyrightApplicationResponse.data.id
}
}
return keysToCamel(result)
}
Expand All @@ -85,50 +110,41 @@ export default class Repository {
}).then(response => 'Bearer ' + response.data.access_token)
.catch(error => this.handleError(error))

return result
localStorage.accessToken = result
}

async _getCurrentUserInfo (accessToken) {
let result
if (accessToken) {
result = await axios({
url: '/api/v1/currentuserapi/current-user',
method: 'GET',
headers: {
Authorization: accessToken
}
}).then(response => response.data.user)
.catch(error => this.handleError(error))
} else {
result = {
error: 'Could not procure access token'
async _getCurrentUserInfo () {
let result = await axios({
url: '/api/v1/currentuserapi/current-user',
method: 'GET',
headers: {
Authorization: localStorage.accessToken
}
}
}).then(response => response.data.user)
.catch(error => this.handleError(error))

return keysToCamel(result)
}

async _generateServiceRequest () {
const accessToken = await this._getAccessToken()
const serviceRequestId = await axios({
url: '/api/v1/copyrightapplicationservicerequestapi/generate-service-request',
method: 'GET',
headers: {
Authorization: accessToken
Authorization: localStorage.accessToken
}
}).then(response => response.data.id)
.catch(error => this.handleError(error))
return serviceRequestId
}

async _uploadFile (formData, serviceRequestId) {
const accessToken = await this._getAccessToken()
const response = await axios({
url: '/api/v1/copyrightapplicationfileapi/file-upload?service_request_id=' + serviceRequestId,
method: 'POST',
data: formData,
headers: {
Authorization: accessToken
Authorization: localStorage.accessToken
}
}).then(response => response.data.file_url)
.catch(error => this.handleError(error))
Expand All @@ -137,13 +153,12 @@ export default class Repository {
}

async _downloadFile (url, fileName) {
const accessToken = await this._getAccessToken()
axios({
url,
method: 'GET',
responseType: 'blob',
headers: {
Authorization: accessToken
Authorization: localStorage.accessToken
}
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]))
Expand Down
Loading

0 comments on commit 89dec36

Please sign in to comment.