Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

close #1649

Closed

close #1649

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
709d601
fixed migration org uuid
elraphty Apr 26, 2024
78e3470
added difference in budget
elraphty Apr 26, 2024
84b7e5e
Merge pull request #1619 from stakwork/fix/migrations_and_update_balance
elraphty Apr 27, 2024
5575277
fixed csv export bug
elraphty Apr 30, 2024
3ea8f77
Merge pull request #1623 from stakwork/fix/csv-export
elraphty Apr 30, 2024
0a3f966
Added cypress tests and objects
fvalentiner Apr 30, 2024
687a5fb
fixed workspace name not being displayed
elraphty Apr 30, 2024
4ff090d
Changed Bounty to NewBounty
elraphty Apr 30, 2024
a341797
Merge pull request #1625 from stakwork/fix/admin_bounties_organization
elraphty Apr 30, 2024
377c27f
added workspace to admin
elraphty May 1, 2024
4dac8d0
added workspace for payment and bounty metrics
elraphty May 1, 2024
fe70a56
Merge pull request #1628 from stakwork/feature-add-features-endpoints
elraphty May 1, 2024
298a07b
Added feature endpoints
AbdulWahab3181 May 2, 2024
ff72560
updated workspace for admin
elraphty May 2, 2024
3008133
Addressed changes
AbdulWahab3181 May 2, 2024
1861bf5
changes
elraphty May 2, 2024
3c8fdc1
Merge pull request #1629 from AbdulWahab3181/feature/add-feature-endp…
elraphty May 2, 2024
b8d2b1f
added assignee stats
elraphty May 3, 2024
1438e44
fixed tests
elraphty May 3, 2024
e6c08b3
Merge pull request #1627 from stakwork/feat/admin_workspace
elraphty May 3, 2024
12ee59e
Merge pull request #1630 from stakwork/feature-add-features-to-worksp…
elraphty May 3, 2024
97b8b4b
Add Endpoints for Workspace Repositories
MirzaHanan May 3, 2024
ba5ebd8
Merge branch 'master' into Add-Endpoints-for-Workspace-Repo
MirzaHanan May 3, 2024
356f165
Merge pull request #1631 from MirzaHanan/Add-Endpoints-for-Workspace-…
elraphty May 6, 2024
66008d9
fixeed payment history
elraphty May 7, 2024
fac27f3
Merge pull request #1632 from stakwork/fix/payments
elraphty May 7, 2024
bbbbe46
fixed bounty budgets addition
elraphty May 7, 2024
7d4c4e5
Merge pull request #1633 from stakwork/fix/payments
elraphty May 7, 2024
39bf36b
workspace
elraphty May 7, 2024
acae85b
Merge pull request #1634 from stakwork/fix/payments
elraphty May 7, 2024
ee9f22f
rename org
elraphty May 7, 2024
4f33ba9
Merge pull request #1635 from stakwork/fix/payments
elraphty May 7, 2024
96fb0f9
fixed deduct payment
elraphty May 9, 2024
39b6548
Merge pull request #1636 from stakwork/feat/deduct_payment
elraphty May 9, 2024
578d5d9
Merge pull request #1641 from stakwork/feature-add-features-to-worksp…
elraphty May 12, 2024
7c11757
added paginationto feature
elraphty May 14, 2024
5d9a2cc
Merge pull request #1645 from stakwork/fix/feature_db
elraphty May 14, 2024
1c54cf0
cypress fixed
MahtabBukhari May 16, 2024
c0143bd
Merge branch 'feature-add-features-to-workspaces-modify-delete' into …
MahtabBukhari May 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions cypress/e2e/02_repositories.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { User, HostName, Workspaces, Repositories } from '../support/objects/objects';


describe('Create Repositories for Workspace', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
for(let i = 0; i <= 1; i++) {
cy.request({
method: 'POST',
url: `${HostName}/workspaces/repositories`,
headers: { 'x-jwt': `${value}` },
body: Repositories[i]
}).its('body').then(body => {
expect(body).to.have.property('name').and.equal(Repositories[i].name.trim());
expect(body).to.have.property('url').and.equal(Repositories[i].url.trim());
});
}
})
})
})


describe('Check Repositories Values', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
cy.request({
method: 'GET',
url: `${HostName}/workspaces/repositories/` + Repositories[0].workspace_uuid,
headers: { 'x-jwt': `${ value }` },
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body[0]).to.have.property('name', Repositories[0].name.trim())
expect(resp.body[0]).to.have.property('url', Repositories[0].url.trim())
expect(resp.body[1]).to.have.property('name', Repositories[1].name.trim())
expect(resp.body[1]).to.have.property('url', Repositories[1].url.trim())
})
})
})
})
76 changes: 43 additions & 33 deletions cypress/e2e/03_features.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ describe('Create Features for Workspace', () => {
url: `${HostName}/features`,
headers: { 'x-jwt': `${value}` },
body: Features[i]
}).its('body').should('have.property', 'name', Features[i].name.trim())
.its('body').should('have.property', 'brief', Features[i].brief.trim())
.its('body').should('have.property', 'requirements', Features[i].requirements.trim())
.its('body').should('have.property', 'architecture', Features[i].architecture.trim())
}).its('body').then(body => {
expect(body).to.have.property('name').and.equal(Features[i].name.trim());
expect(body).to.have.property('brief').and.equal(Features[i].brief.trim());
expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim());
expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim());
});
}
})
})
Expand All @@ -32,10 +34,12 @@ describe('Modify name for Feature', () => {
uuid: Features[i].uuid,
name: Features[i].name + "_addtext"
}
}).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext")
.its('body').should('have.property', 'brief', Features[i].brief.trim())
.its('body').should('have.property', 'requirements', Features[i].requirements.trim())
.its('body').should('have.property', 'architecture', Features[i].architecture.trim())
}).its('body').then(body => {
expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext");
expect(body).to.have.property('brief').and.equal(Features[i].brief.trim());
expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim());
expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim());
});
}
})
})
Expand All @@ -53,10 +57,12 @@ describe('Modify brief for Feature', () => {
uuid: Features[i].uuid,
brief: Features[i].brief + "_addtext"
}
}).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext")
.its('body').should('have.property', 'brief', Features[i].brief.trim() + "_addtext")
.its('body').should('have.property', 'requirements', Features[i].requirements.trim())
.its('body').should('have.property', 'architecture', Features[i].architecture.trim())
}).its('body').then(body => {
expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext");
expect(body).to.have.property('brief').and.equal(Features[i].brief.trim() + " _addtext");
expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim());
expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim());
});
}
})
})
Expand All @@ -74,10 +80,12 @@ describe('Modify requirements for Feature', () => {
uuid: Features[i].uuid,
requirements: Features[i].requirements + "_addtext"
}
}).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext")
.its('body').should('have.property', 'brief', Features[i].brief.trim() + "_addtext")
.its('body').should('have.property', 'requirements', Features[i].requirements.trim() + "_addtext")
.its('body').should('have.property', 'architecture', Features[i].architecture.trim())
}).its('body').then(body => {
expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext");
expect(body).to.have.property('brief').and.equal(Features[i].brief.trim() + " _addtext");
expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim() + " _addtext");
expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim());
});
}
})
})
Expand All @@ -95,10 +103,12 @@ describe('Modify architecture for Feature', () => {
uuid: Features[i].uuid,
architecture: Features[i].architecture + "_addtext"
}
}).its('body').should('have.property', 'name', Features[i].name.trim() + "_addtext")
.its('body').should('have.property', 'brief', Features[i].brief.trim() + "_addtext")
.its('body').should('have.property', 'requirements', Features[i].requirements.trim() + "_addtext")
.its('body').should('have.property', 'architecture', Features[i].architecture.trim() + "_addtext")
}).its('body').then(body => {
expect(body).to.have.property('name').and.equal(Features[i].name.trim() + " _addtext");
expect(body).to.have.property('brief').and.equal(Features[i].brief.trim() + " _addtext");
expect(body).to.have.property('requirements').and.equal(Features[i].requirements.trim() + " _addtext");
expect(body).to.have.property('architecture').and.equal(Features[i].architecture.trim() + " _addtext");
});
}
})
})
Expand All @@ -112,15 +122,16 @@ describe('Get Features for Workspace', () => {
method: 'GET',
url: `${HostName}/workspaces/${Features[0].workspace_uuid}/features`, //changed from url: `${HostName}/features/forworkspace/` + Features[0].workspace_uuid, please update the routes file and any other change needed.
headers: { 'x-jwt': `${ value }` },
body: {}
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)
for(let i = 0; i <= 2; i++) {
expect(resp.body[i]).to.have.property('name', Features[i].name.trim() + "_addtext")
expect(resp.body[i]).to.have.property('brief', Features[i].brief.trim() + "_addtext")
expect(resp.body[i]).to.have.property('requirements', Features[i].requirements.trim() + "_addtext")
expect(resp.body[i]).to.have.property('architecture', Features[i].architecture.trim() + "_addtext")
}
resp.body.forEach((feature) => {
const expectedFeature = Features.find(f => f.uuid === feature.uuid);
expect(feature).to.have.property('name', expectedFeature.name.trim() + " _addtext");
expect(feature).to.have.property('brief', expectedFeature.brief.trim() + " _addtext");
expect(feature).to.have.property('requirements', expectedFeature.requirements.trim() + " _addtext");
expect(feature).to.have.property('architecture', expectedFeature.architecture.trim() + " _addtext");
});
})
})
})
Expand All @@ -134,13 +145,13 @@ describe('Get Feature by uuid', () => {
method: 'GET',
url: `${HostName}/features/`+ Features[i].uuid,
headers: { 'x-jwt': `${ value }` },
body: {}
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body).to.have.property('name', Features[i].name.trim() + "_addtext")
expect(resp.body).to.have.property('brief', Features[i].brief.trim() + "_addtext")
expect(resp.body).to.have.property('requirements', Features[i].requirements.trim() + "_addtext")
expect(resp.body).to.have.property('architecture', Features[i].architecture.trim() + "_addtext")
expect(resp.body).to.have.property('name', Features[i].name.trim() + " _addtext")
expect(resp.body).to.have.property('brief', Features[i].brief.trim() + " _addtext")
expect(resp.body).to.have.property('requirements', Features[i].requirements.trim() + " _addtext")
expect(resp.body).to.have.property('architecture', Features[i].architecture.trim() + " _addtext")
})
}
})
Expand Down Expand Up @@ -175,4 +186,3 @@ describe('Check delete by uuid', () => {
})
})
})
})
10 changes: 5 additions & 5 deletions cypress/support/objects/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const Repositories = [
url: ' https://github.com/stakwork/sphinx-tribes-frontend '
},
{
uuid: 'com1t3gn1e4a4qu3tnlg',
uuid: 'com1t3gn1e4a4qu3thss',
workspace_uuid: 'cohob00n1e4808utqel0',
name: ' backend ',
url: ' https://github.com/stakwork/sphinx-tribes '
Expand Down Expand Up @@ -100,7 +100,7 @@ export const Features = [
' the base from which every technical decition relays on.<br/>' +
'We are going to leverage AI to help the PM write better definitions.<br/>' +
'The fields that would benefit form AI assistance are: mission, tactics, ' +
'feature brief and feature user stories',
'feature brief and feature user stories ',
requirements: ' Create a new page for a conversation format between the PM and the LLM<br/>' +
'Rely as much as possible on stakwork workflows<br/>' +
'Have history of previous definitions ',
Expand All @@ -110,17 +110,17 @@ export const Features = [
'Front<br/><br/> ',
},
{
uuid: 'com1l5on1e49tucv350g',
uuid: 'com1l5on1e49tucv350h',
workspace_uuid: 'cohob00n1e4808utqel0',
name: ' AI Assited relation between text fields ',
priority: 2,
brief: ' A product and feature\'s various definition fields: mission, tactics, ' +
'feature brief, user stories, requirements and architecture should have some ' +
'relation between each other.<br/>' + 'One way to do that is to leverage an LLM ' +
'to discern the parts of the defintion that have a connection to other definitions.<br/>' +
'The UI will need to show the user how each definition is related to other defintions.',
'The UI will need to show the user how each definition is related to other defintions. ',
requirements: 'Create a new process after a Feature text has changed. It should use the LLM to ' +
'determine de relationship between parts of the text.',
'determine de relationship between parts of the text. ',
architecture: 'Describe the architecture of the feature with the following sections:' +
'<br/><br/>Wireframes<br/><br/>Visual Schematics<br/><br/>Object Definition<br/><br/>' +
'DB Schema Changes<br/><br/>UX<br/><br/>CI/CD<br/><br/>Changes<br/><br/>Endpoints<br/><br/>' +
Expand Down
10 changes: 10 additions & 0 deletions db/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ func InitDB() {
db.AutoMigrate(&ConnectionCodes{})
db.AutoMigrate(&BountyRoles{})
db.AutoMigrate(&UserInvoiceData{})
db.AutoMigrate(&WorkspaceRepositories{})
db.AutoMigrate(&WorkspaceFeatures{})

DB.MigrateTablesWithOrgUuid()
DB.MigrateOrganizationToWorkspace()
Expand Down Expand Up @@ -177,6 +179,8 @@ func (db database) MigrateTablesWithOrgUuid() {
if !db.db.Migrator().HasTable("bounty") {
if !db.db.Migrator().HasColumn(Bounty{}, "workspace_uuid") {
db.db.AutoMigrate(&Bounty{})
} else {
db.db.AutoMigrate(&NewBounty{})
}
}
if !db.db.Migrator().HasTable("budget_histories") {
Expand All @@ -187,16 +191,22 @@ func (db database) MigrateTablesWithOrgUuid() {
if !db.db.Migrator().HasTable("payment_histories") {
if !db.db.Migrator().HasColumn(PaymentHistory{}, "workspace_uuid") {
db.db.AutoMigrate(&PaymentHistory{})
} else {
db.db.AutoMigrate(&NewPaymentHistory{})
}
}
if !db.db.Migrator().HasTable("invoice_list") {
if !db.db.Migrator().HasColumn(InvoiceList{}, "workspace_uuid") {
db.db.AutoMigrate(&InvoiceList{})
} else {
db.db.AutoMigrate(&NewInvoiceList{})
}
}
if !db.db.Migrator().HasTable("bounty_budgets") {
if !db.db.Migrator().HasColumn(BountyBudget{}, "workspace_uuid") {
db.db.AutoMigrate(&BountyBudget{})
} else {
db.db.AutoMigrate(&NewBountyBudget{})
}
}
if !db.db.Migrator().HasTable("workspace_user_roles") {
Expand Down
2 changes: 1 addition & 1 deletion db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ func (db database) GetAllBounties(r *http.Request) []NewBounty {
languageArray := strings.Split(languages, ",")
languageLength := len(languageArray)

if workspaceUuid != "" && orgUuid != "" {
if workspaceUuid == "" && orgUuid != "" {
workspaceUuid = orgUuid
}

Expand Down
86 changes: 86 additions & 0 deletions db/features.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package db

import (
"errors"
"fmt"
"github.com/stakwork/sphinx-tribes/utils"
"net/http"
"strings"
"time"
)

func (db database) GetFeaturesByWorkspaceUuid(uuid string, r *http.Request) []WorkspaceFeatures {
offset, limit, sortBy, direction, _ := utils.GetPaginationParams(r)

orderQuery := ""
limitQuery := ""

ms := []WorkspaceFeatures{}

if sortBy != "" && direction != "" {
orderQuery = "ORDER BY " + sortBy + " " + direction
} else {
orderQuery = "ORDER BY created DESC"
}

if limit > 1 {
limitQuery = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset)
}

query := `SELECT * FROM public.workspace_features WHERE workspace_uuid = '` + uuid + `'`

allQuery := query + " " + orderQuery + " " + limitQuery

theQuery := db.db.Raw(allQuery)

theQuery.Scan(&ms)

return ms
}

func (db database) GetWorkspaceFeaturesCount(uuid string) int64 {
var count int64
db.db.Model(&WorkspaceFeatures{}).Where("workspace_uuid = ?", uuid).Count(&count)
return count
}

func (db database) GetFeatureByUuid(uuid string) WorkspaceFeatures {
ms := WorkspaceFeatures{}

db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", uuid).Find(&ms)

return ms
}

func (db database) CreateOrEditFeature(m WorkspaceFeatures) (WorkspaceFeatures, error) {
m.Name = strings.TrimSpace(m.Name)
m.Brief = strings.TrimSpace(m.Brief)
m.Requirements = strings.TrimSpace(m.Requirements)
m.Architecture = strings.TrimSpace(m.Architecture)
now := time.Now()
m.Updated = &now

var existing WorkspaceFeatures
result := db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", m.Uuid).First(&existing)
if result.RowsAffected == 0 {

m.Created = &now
db.db.Create(&m)
} else {

db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", m.Uuid).Updates(m)
}

db.db.Model(&WorkspaceFeatures{}).Where("uuid = ?", m.Uuid).First(&m)
return m, nil
}

func (db database) DeleteFeatureByUuid(uuid string) error {
result := db.db.Where("uuid = ?", uuid).Delete(&WorkspaceFeatures{})

if result.RowsAffected == 0 {
return errors.New("no feature found to delete")
}
return nil

}
30 changes: 19 additions & 11 deletions db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,29 @@ type Database interface {
DeleteAllUsersFromWorkspace(uuid string) error
GetFilterStatusCount() FilterStattuCount
UserHasManageBountyRoles(pubKeyFromAuth string, uuid string) bool
BountiesPaidPercentage(r PaymentDateRange) uint
TotalSatsPosted(r PaymentDateRange) uint
TotalSatsPaid(r PaymentDateRange) uint
SatsPaidPercentage(r PaymentDateRange) uint
AveragePaidTime(r PaymentDateRange) uint
AverageCompletedTime(r PaymentDateRange) uint
TotalBountiesPosted(r PaymentDateRange) int64
TotalPaidBounties(r PaymentDateRange) int64
NewHuntersPaid(r PaymentDateRange) int64
TotalHuntersPaid(r PaymentDateRange) int64
BountiesPaidPercentage(r PaymentDateRange, workspace string) uint
TotalSatsPosted(r PaymentDateRange, workspace string) uint
TotalSatsPaid(r PaymentDateRange, workspace string) uint
SatsPaidPercentage(r PaymentDateRange, workspace string) uint
AveragePaidTime(r PaymentDateRange, workspace string) uint
AverageCompletedTime(r PaymentDateRange, workspace string) uint
TotalBountiesPosted(r PaymentDateRange, workspace string) int64
TotalPaidBounties(r PaymentDateRange, workspace string) int64
TotalAssignedBounties(r PaymentDateRange, workspace string) int64
NewHuntersPaid(r PaymentDateRange, workspace string) int64
TotalHuntersPaid(r PaymentDateRange, workspace string) int64
GetPersonByPubkey(pubkey string) Person
GetBountiesByDateRange(r PaymentDateRange, re *http.Request) []Bounty
GetBountiesByDateRange(r PaymentDateRange, re *http.Request) []NewBounty
GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Request) int64
GetBountiesProviders(r PaymentDateRange, re *http.Request) []Person
PersonUniqueNameFromName(name string) (string, error)
ProcessAlerts(p Person)
UserHasAccess(pubKeyFromAuth string, uuid string, role string) bool
CreateWorkspaceRepository(m WorkspaceRepositories) (WorkspaceRepositories, error)
GetWorkspaceRepositorByWorkspaceUuid(uuid string) []WorkspaceRepositories
CreateOrEditFeature(m WorkspaceFeatures) (WorkspaceFeatures, error)
GetFeaturesByWorkspaceUuid(uuid string, r *http.Request) []WorkspaceFeatures
GetWorkspaceFeaturesCount(uuid string) int64
GetFeatureByUuid(uuid string) WorkspaceFeatures
DeleteFeatureByUuid(uuid string) error
}
Loading
Loading