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

Add Phases to Features #1642

Merged
merged 16 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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())
})
})
})
})
120 changes: 120 additions & 0 deletions cypress/e2e/06_phases.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { User, HostName, UserStories, Phases } from '../support/objects/objects';

describe('Create Phases for Feature', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
for(let i = 0; i <= 2; i++) {
cy.request({
method: 'POST',
url: `${HostName}/features/phase`,
headers: { 'x-jwt': `${value}` },
body: Phases[i]
}).its('body').then(body => {
expect(body).to.have.property('uuid').and.equal(Phases[i].uuid.trim());
expect(body).to.have.property('feature_uuid').and.equal(Phases[i].feature_uuid.trim());
expect(body).to.have.property('name').and.equal(Phases[i].name.trim());
expect(body).to.have.property('priority').and.equal(Phases[i].priority);
});
}
})
})
})

describe('Modify phases name', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
for(let i = 0; i <= 2; i++) {
cy.request({
method: 'POST',
url: `${HostName}/features/phase`,
headers: { 'x-jwt': `${value}` },
body: {
uuid: Phases[i].uuid,
name: Phases[i].name + "_addtext"
}
}).its('body').then(body => {
expect(body).to.have.property('uuid').and.equal(Phases[i].uuid.trim());
expect(body).to.have.property('feature_uuid').and.equal(Phases[i].feature_uuid.trim());
expect(body).to.have.property('name').and.equal(Phases[i].name.trim() + " _addtext");
expect(body).to.have.property('priority').and.equal(Phases[i].priority);
});
}
})
})
})

describe('Get phases for feature', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
cy.request({
method: 'GET',
url: `${HostName}/features/${Phases[0].feature_uuid}/phase`,
headers: { 'x-jwt': `${ value }` },
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)

resp.body.forEach((phase, index) => {
// Directly use index to compare with the expected phase in the same order
const expectedPhase = Phases[index];
expect(phase.uuid).to.equal(expectedPhase.uuid.trim());
expect(phase.feature_uuid).to.equal(expectedPhase.feature_uuid.trim());
expect(phase.name).to.equal(expectedPhase.name.trim() + " _addtext");
expect(phase.priority).to.equal(expectedPhase.priority);
});
})
})
})
})

describe('Get phase by uuid', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
for(let i = 0; i <= 2; i++) {
cy.request({
method: 'GET',
url: `${HostName}/features/${Phases[0].feature_uuid}/phase/${Phases[i].uuid}`,
headers: { 'x-jwt': `${ value }` },
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body).to.have.property('uuid').and.equal(Phases[i].uuid.trim());
expect(resp.body).to.have.property('feature_uuid').and.equal(Phases[i].feature_uuid.trim());
expect(resp.body).to.have.property('name').and.equal(Phases[i].name.trim() + " _addtext");
expect(resp.body).to.have.property('priority').and.equal(Phases[i].priority);
})
}
})
})
})

describe('Delete phase by uuid', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
cy.request({
method: 'DELETE',
url: `${HostName}/features/${Phases[0].feature_uuid}/phase/${Phases[0].uuid}`,
headers: { 'x-jwt': `${ value }` },
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)
})
})
})
})

describe('Check delete by uuid', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
cy.request({
method: 'GET',
url: `${HostName}/features/${Phases[0].feature_uuid}/phase/${Phases[0].uuid}`,
headers: { 'x-jwt': `${ value }` },
body: {},
failOnStatusCode: false
}).then((resp) => {
expect(resp.status).to.eq(404);
})
})
})
})
8 changes: 4 additions & 4 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 @@ -138,7 +138,7 @@ export const UserStories = [
];

export const Phases = [
{ uuid: 'com1msgn1e4a0ts5kls0', feature_uuid: 'com1kson1e49th88dbg0', name: ' MVP ' },
{ uuid: 'com1mvgn1e4a1879uiv0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 2 ' },
{ uuid: 'com1n2gn1e4a1i8p60p0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 3 ' },
{ uuid: 'com1msgn1e4a0ts5kls0', feature_uuid: 'com1kson1e49th88dbg0', name: ' MVP ', priority: 0 },
{ uuid: 'com1mvgn1e4a1879uiv0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 2 ', priority: 1 },
{ uuid: 'com1n2gn1e4a1i8p60p0', feature_uuid: 'com1kson1e49th88dbg0', name: ' Phase 3 ', priority: 2 },
];
2 changes: 2 additions & 0 deletions db/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ func InitDB() {
db.AutoMigrate(&ConnectionCodes{})
db.AutoMigrate(&BountyRoles{})
db.AutoMigrate(&UserInvoiceData{})
db.AutoMigrate(&WorkspaceRepositories{})
db.AutoMigrate(&WorkspaceFeatures{})
db.AutoMigrate(&FeaturePhase{})

DB.MigrateTablesWithOrgUuid()
DB.MigrateOrganizationToWorkspace()
Expand Down
84 changes: 80 additions & 4 deletions db/features.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
package db

import (
"errors"
"fmt"
"net/http"
"strings"
"time"

"github.com/stakwork/sphinx-tribes/utils"
)

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

orderQuery := ""
limitQuery := ""

ms := []WorkspaceFeatures{}

db.db.Model(&WorkspaceFeatures{}).Where("workspace_uuid = ?", uuid).Order("Created").Find(&ms)
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{}

Expand All @@ -35,7 +67,51 @@ func (db database) CreateOrEditFeature(m WorkspaceFeatures) (WorkspaceFeatures,
db.db.Create(&m)
}

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

return m, nil
}

func (db database) CreateOrEditFeaturePhase(phase FeaturePhase) (FeaturePhase, error) {
phase.Name = strings.TrimSpace(phase.Name)

now := time.Now()
phase.Updated = &now

existingPhase := FeaturePhase{}
result := db.db.Model(&FeaturePhase{}).Where("uuid = ?", phase.Uuid).First(&existingPhase)

if result.RowsAffected == 0 {

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

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

db.db.Model(&FeaturePhase{}).Where("uuid = ?", phase.Uuid).Find(&phase)

return phase, nil
}

func (db database) GetPhasesByFeatureUuid(featureUuid string) []FeaturePhase {
phases := []FeaturePhase{}
db.db.Model(&FeaturePhase{}).Where("feature_uuid = ?", featureUuid).Order("Created ASC").Find(&phases)
return phases
}

func (db database) GetFeaturePhaseByUuid(featureUuid, phaseUuid string) (FeaturePhase, error) {
phase := FeaturePhase{}
result := db.db.Model(&FeaturePhase{}).Where("feature_uuid = ? AND uuid = ?", featureUuid, phaseUuid).First(&phase)
if result.RowsAffected == 0 {
return phase, errors.New("no phase found")
}
return phase, nil
}

func (db database) DeleteFeaturePhase(featureUuid, phaseUuid string) error {
result := db.db.Where("feature_uuid = ? AND uuid = ?", featureUuid, phaseUuid).Delete(&FeaturePhase{})
if result.RowsAffected == 0 {
return errors.New("no phase found to delete")
}
return nil
}
9 changes: 8 additions & 1 deletion db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,14 @@ type Database interface {
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) []WorkspaceFeatures
GetFeaturesByWorkspaceUuid(uuid string, r *http.Request) []WorkspaceFeatures
GetWorkspaceFeaturesCount(uuid string) int64
GetFeatureByUuid(uuid string) WorkspaceFeatures
CreateOrEditFeaturePhase(phase FeaturePhase) (FeaturePhase, error)
GetPhasesByFeatureUuid(featureUuid string) []FeaturePhase
GetFeaturePhaseByUuid(featureUuid, phaseUuid string) (FeaturePhase, error)
DeleteFeaturePhase(featureUuid, phaseUuid string) error
}
29 changes: 26 additions & 3 deletions db/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -551,11 +551,23 @@ type WorkspaceUsersData struct {
Person
}

type WorkspaceRepositories struct {
ID uint `json:"id"`
Uuid string `gorm:"not null" json:"uuid"`
WorkspaceUuid string `gorm:"not null" json:"workspace_uuid"`
Name string `gorm:"not null" json:"name"`
Url string `json:"url"`
Created *time.Time `json:"created"`
Updated *time.Time `json:"updated"`
CreatedBy string `json:"created_by"`
UpdatedBy string `json:"updated_by"`
}

type WorkspaceFeatures struct {
ID uint `json:"id"`
Uuid string `json:"uuid"`
WorkspaceUuid string `json:"workspace_uuid"`
Name string `json:"name"`
Uuid string `gorm:"not null" json:"uuid"`
WorkspaceUuid string `gorm:"not null" json:"workspace_uuid"`
Name string `gorm:"not null" json:"name"`
Brief string `json:"brief"`
Requirements string `json:"requirements"`
Architecture string `json:"architecture"`
Expand All @@ -565,6 +577,17 @@ type WorkspaceFeatures struct {
UpdatedBy string `json:"updated_by"`
}

type FeaturePhase struct {
Uuid string `json:"uuid" gorm:"primary_key"`
FeatureUuid string `json:"feature_uuid"`
Name string `json:"name"`
Priority int `json:"priority"`
Created *time.Time `json:"created"`
Updated *time.Time `json:"updated"`
CreatedBy string `json:"created_by"`
UpdatedBy string `json:"updated_by"`
}

type BountyRoles struct {
Name string `json:"name"`
}
Expand Down
24 changes: 24 additions & 0 deletions db/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"time"

"github.com/stakwork/sphinx-tribes/utils"
Expand Down Expand Up @@ -57,6 +58,29 @@ func (db database) CreateOrEditWorkspace(m Workspace) (Workspace, error) {
return m, nil
}

func (db database) CreateWorkspaceRepository(m WorkspaceRepositories) (WorkspaceRepositories, error) {
m.Name = strings.TrimSpace(m.Name)
m.Url = strings.TrimSpace(m.Url)

now := time.Now()
m.Updated = &now

if db.db.Model(&m).Where("uuid = ?", m.Uuid).Updates(&m).RowsAffected == 0 {
m.Created = &now
db.db.Create(&m)
}

return m, nil
}

func (db database) GetWorkspaceRepositorByWorkspaceUuid(uuid string) []WorkspaceRepositories {
ms := []WorkspaceRepositories{}

db.db.Model(&WorkspaceRepositories{}).Where("workspace_uuid = ?", uuid).Order("Created").Find(&ms)

return ms
}

func (db database) GetWorkspaceUsers(uuid string) ([]WorkspaceUsersData, error) {
ms := []WorkspaceUsersData{}

Expand Down
Loading
Loading