Skip to content

Commit

Permalink
Merge pull request #1643 from MirzaHanan/feature-add-user-stories
Browse files Browse the repository at this point in the history
Implementation: Adding User Stories to Features
  • Loading branch information
elraphty authored May 16, 2024
2 parents 74c3a0a + 4174747 commit 67c47a7
Show file tree
Hide file tree
Showing 13 changed files with 619 additions and 51 deletions.
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())
})
})
})
})
31 changes: 16 additions & 15 deletions cypress/e2e/04_user_stories.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('Modify user story description', () => {
}).its('body').then(body => {
expect(body).to.have.property('uuid').and.equal(UserStories[i].uuid.trim());
expect(body).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim());
expect(body).to.have.property('description').and.equal(UserStories[i].description.trim() + "_addtext");
expect(body).to.have.property('description').and.equal(UserStories[i].description.trim() + " _addtext");
expect(body).to.have.property('priority').and.equal(UserStories[i].priority);
});
}
Expand All @@ -56,7 +56,7 @@ describe('Get user stories for feature', () => {
for(let i = 0; i <= 5; i++) {
expect(resp.body[i]).to.have.property('uuid').and.equal(UserStories[i].uuid.trim());
expect(resp.body[i]).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim());
expect(resp.body[i]).to.have.property('description').and.equal(UserStories[i].description.trim() + "_addtext");
expect(resp.body[i]).to.have.property('description').and.equal(UserStories[i].description.trim() + " _addtext");
expect(resp.body[i]).to.have.property('priority').and.equal(UserStories[i].priority);
}
})
Expand All @@ -71,19 +71,19 @@ describe('Get story by uuid', () => {
cy.request({
method: 'GET',
url: `${HostName}/features/${UserStories[0].feature_uuid}/story/${UserStories[i].uuid}`,
headers: { 'x-jwt': `${ value }` },
body: {}
headers: { 'x-jwt': `${value}` },
body: {}
}).then((resp) => {
expect(resp.status).to.eq(200)
expect(resp.body[i]).to.have.property('uuid').and.equal(UserStories[i].uuid.trim());
expect(resp.body[i]).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim());
expect(resp.body[i]).to.have.property('description').and.equal(UserStories[i].description.trim() + "_addtext");
expect(resp.body[i]).to.have.property('priority').and.equal(UserStories[i].priority);
})
expect(resp.status).to.eq(200);
expect(resp.body).to.have.property('uuid').and.equal(UserStories[i].uuid.trim());
expect(resp.body).to.have.property('feature_uuid').and.equal(UserStories[i].feature_uuid.trim());
expect(resp.body).to.have.property('description').and.equal(UserStories[i].description.trim() + " _addtext");
expect(resp.body).to.have.property('priority').and.equal(UserStories[i].priority);
});
}
})
})
})
});
});
});

describe('Delete story by uuid', () => {
it('passes', () => {
Expand All @@ -104,10 +104,11 @@ describe('Check delete by uuid', () => {
it('passes', () => {
cy.upsertlogin(User).then(value => {
cy.request({
method: 'GET',
method: 'DELETE',
url: `${HostName}/features/${UserStories[0].feature_uuid}/story/${UserStories[0].uuid}`,
headers: { 'x-jwt': `${ value }` },
body: {}
body: {},
failOnStatusCode: false
}).then((resp) => {
expect(resp.status).to.eq(404);
})
Expand Down
2 changes: 1 addition & 1 deletion 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
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(&FeatureStory{})

DB.MigrateTablesWithOrgUuid()
DB.MigrateOrganizationToWorkspace()
Expand Down
91 changes: 87 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,58 @@ 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) CreateOrEditFeatureStory(story FeatureStory) (FeatureStory, error) {
story.Description = strings.TrimSpace(story.Description)

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

existingStory := FeatureStory{}
result := db.db.Model(&FeatureStory{}).Where("uuid = ?", story.Uuid).First(&existingStory)

if result.RowsAffected == 0 {

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

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

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

return story, nil
}

func (db database) GetFeatureStoriesByFeatureUuid(featureUuid string) ([]FeatureStory, error) {
var stories []FeatureStory
result := db.db.Where("feature_uuid = ?", featureUuid).Find(&stories)
if result.Error != nil {
return nil, result.Error
}

for i := range stories {
stories[i].Description = strings.TrimSpace(stories[i].Description)
}
return stories, nil
}

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

func (db database) DeleteFeatureStoryByUuid(featureUuid, storyUuid string) error {
result := db.db.Where("feature_uuid = ? AND uuid = ?", featureUuid, storyUuid).Delete(&FeatureStory{})
if result.RowsAffected == 0 {
return errors.New("no story 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
CreateOrEditFeatureStory(story FeatureStory) (FeatureStory, error)
GetFeatureStoriesByFeatureUuid(featureUuid string) ([]FeatureStory, error)
GetFeatureStoryByUuid(featureUuid, storyUuid string) (FeatureStory, error)
DeleteFeatureStoryByUuid(featureUuid, storyUuid string) error
}
30 changes: 27 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 Down Expand Up @@ -656,6 +668,18 @@ type BudgetHistory struct {
PaymentType PaymentType `json:"payment_type"`
}

type FeatureStory struct {
ID uint `json:"id"`
Uuid string `json:"uuid"`
FeatureUuid string `json:"feature_uuid"`
Description string `json:"description"`
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 BudgetHistoryData struct {
BudgetHistory
SenderName string `json:"sender_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

0 comments on commit 67c47a7

Please sign in to comment.