diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..eaf2d0bba --- /dev/null +++ b/package-lock.json @@ -0,0 +1,156 @@ +{ + "name": "dega", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "dega", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "moment": "^2.30.1" + }, + "devDependencies": { + "@playwright/test": "^1.44.1", + "@types/node": "^20.14.2" + } + }, + "node_modules/@playwright/test": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", + "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", + "dev": true, + "dependencies": { + "playwright": "1.44.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/playwright": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", + "dev": true, + "dependencies": { + "playwright-core": "1.44.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + }, + "dependencies": { + "@playwright/test": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", + "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", + "dev": true, + "requires": { + "playwright": "1.44.1" + } + }, + "@types/node": { + "version": "20.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz", + "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, + "playwright": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.44.1" + } + }, + "playwright-core": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", + "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + } +} diff --git a/package.json b/package.json index aa982a619..30fd1117f 100644 --- a/package.json +++ b/package.json @@ -18,5 +18,7 @@ "devDependencies": { "@playwright/test": "^1.44.1", "@types/node": "^20.14.2" + }, + "dependencies": { } } diff --git a/server/service/core/action/medium/list.go b/server/service/core/action/medium/list.go index 44affd7e9..7442ffd92 100644 --- a/server/service/core/action/medium/list.go +++ b/server/service/core/action/medium/list.go @@ -1,7 +1,9 @@ package medium import ( + "fmt" "net/http" + "time" "github.com/factly/dega-server/service/core/service" "github.com/factly/dega-server/util" @@ -37,9 +39,26 @@ func list(w http.ResponseWriter, r *http.Request) { searchQuery := r.URL.Query().Get("q") sort := r.URL.Query().Get("sort") offset, limit := paginationx.Parse(r.URL.Query()) + dateStr := r.URL.Query().Get("date") + + var year int + var month time.Month + var yearMonthProvided bool + + if dateStr != "" { + layout := "2006-01" + dateInt, err := time.Parse(layout, dateStr) + if err != nil { + fmt.Println("Error parsing date:", err) + return + } + year = dateInt.Year() + month = dateInt.Month() + yearMonthProvided = true + } mediumService := service.GetMediumService() - result, errMessages := mediumService.List(authCtx.SpaceID, offset, limit, searchQuery, sort) + result, errMessages := mediumService.List(authCtx.SpaceID, offset, limit, searchQuery, sort, year, month, yearMonthProvided, dateStr) if errMessages != nil { errorx.Render(w, errMessages) return diff --git a/server/service/core/service/medium.go b/server/service/core/service/medium.go index 407bf358b..0ce74047e 100644 --- a/server/service/core/service/medium.go +++ b/server/service/core/service/medium.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "net/http" "strings" "time" @@ -40,6 +41,7 @@ type Medium struct { type pagingMedium struct { Total int64 `json:"total"` Nodes []model.Medium `json:"nodes"` + Date time.Time `json:"date"` } type MediumService struct { @@ -47,7 +49,7 @@ type MediumService struct { } type IMediumService interface { GetById(sID, id uuid.UUID) (model.Medium, error) - List(sID uuid.UUID, offset, limit int, searchQuery, sort string) (pagingMedium, []errorx.Message) + List(sID uuid.UUID, offset, limit int, searchQuery, sort string, year int, month time.Month, yearMonthProvided bool, dateStr string) (pagingMedium, []errorx.Message) Create(ctx context.Context, sID uuid.UUID, uID string, mediumList []Medium) (pagingMedium, []errorx.Message) Update(sID, id uuid.UUID, uID string, medium *Medium) (model.Medium, []errorx.Message) Delete(sID, id uuid.UUID) []errorx.Message @@ -71,17 +73,36 @@ func (ms MediumService) GetById(sID, id uuid.UUID) (model.Medium, error) { return *result, err } -func (ms MediumService) List(sID uuid.UUID, offset, limit int, searchQuery, sort string) (pagingMedium, []errorx.Message) { +func (ms MediumService) List(sID uuid.UUID, offset, limit int, searchQuery, sort string, year int, month time.Month, yearMonthProvided bool, dateStr string) (pagingMedium, []errorx.Message) { result := pagingMedium{} result.Nodes = make([]model.Medium, 0) + tx := config.DB.Model(&model.Medium{}).Where(&model.Medium{ + SpaceID: sID, + }) + + if yearMonthProvided { + // Validate year and month inputs + if year < 1 || (month < 1 || month > 12) { + return pagingMedium{}, []errorx.Message{errorx.GetMessage("Invalid year or month", http.StatusBadRequest)} + } + + // Add year filter + if year > 0 { + tx = tx.Where("EXTRACT(YEAR FROM created_at) = ?", year) + } + + // Add month filter + if month > 0 && month <= 12 { + tx = tx.Where("EXTRACT(MONTH FROM created_at) = ?", int(month)) + } + + } + if sort != "asc" { sort = "desc" } - - tx := config.DB.Model(&model.Medium{}).Where(&model.Medium{ - SpaceID: sID, - }).Order("created_at " + sort) + tx = tx.Order("created_at " + sort) if searchQuery != "" { diff --git a/studio/src/actions/media.js b/studio/src/actions/media.js index 881bb68dd..5211cb2a6 100644 --- a/studio/src/actions/media.js +++ b/studio/src/actions/media.js @@ -20,12 +20,13 @@ export const getMedia = (query, profile) => { params: query, }) .then((response) => { - dispatch(addMedia(response.data.nodes)); + if (response.data === "") return []; + dispatch(addMedia(response?.data?.nodes)); dispatch( addMediaRequest({ - data: response.data.nodes.map((item) => item.id), + data: response?.data?.nodes.map((item) => item.id), query: query, - total: response.data.total, + total: response?.data?.total, }), ); }) @@ -59,7 +60,6 @@ export const createMedium = (data, profile) => { return axios .post(MEDIA_API, profile ? data[0] : data) .then((response) => { - dispatch(resetMedia()); dispatch(addSuccessNotification('Medium created')); return profile ? response.data : response.data.nodes[0]; }) diff --git a/studio/src/pages/media/components/MediumList.js b/studio/src/pages/media/components/MediumList.js index 1937967cf..a7593b61a 100644 --- a/studio/src/pages/media/components/MediumList.js +++ b/studio/src/pages/media/components/MediumList.js @@ -15,7 +15,7 @@ function MediumList({ data, filters, setFilters }) { xl: 4, xxl: 5, }} - pagination={{ + pagination={data.total > 0 ? { showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} results`, total: data.total, current: filters.page, @@ -24,7 +24,7 @@ function MediumList({ data, filters, setFilters }) { setFilters({ ...filters, page: pageNumber || 1, limit: pageSize }); }, pageSizeOptions: ['10', '15', '20'], - }} + } : false} dataSource={data.media} renderItem={(item) => ( @@ -32,7 +32,6 @@ function MediumList({ data, filters, setFilters }) { { history({ pathname: pathName, @@ -50,7 +52,6 @@ function Media({ permission }) { const node = state.media.req.find((item) => { return deepEqual(item.query, params); }); - if (node) return { media: node.data.map((element) => state.media.details[element]), @@ -59,9 +60,14 @@ function Media({ permission }) { }; return { media: [], total: 0, loading: state.media.loading }; }); + useEffect(() => { - if (form) form.setFieldsValue(new Filters(params)); - }, [params]); + if (form) { + const initialFilters = new Filters(params); + form.setFieldsValue(initialFilters); + } + }, [params, form]); + React.useEffect(() => { fetchMedia(); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -71,6 +77,14 @@ function Media({ permission }) { dispatch(getMedia(filters)); }; + const onDateChange = (date, dateString) => { + const updatedFilters = { + ...filters, + date: dateString, + }; + setFilters(updatedFilters); + }; + return loading ? ( ) : ( @@ -86,7 +100,7 @@ function Media({ permission }) { }} >
{ @@ -111,6 +125,8 @@ function Media({ permission }) { } setFilters({ ...filters, ...changedValues }); } + + console.log(allValues); }} > @@ -178,6 +194,13 @@ function Media({ permission }) { + + + + + + + diff --git a/studio/src/utils/filters.js b/studio/src/utils/filters.js index c9906e8e0..bc7530a8e 100644 --- a/studio/src/utils/filters.js +++ b/studio/src/utils/filters.js @@ -1,6 +1,6 @@ class Filters { constructor( - { q, sort, tag, category, author, status, claimant, rating, podcast, language } = { + { q, sort, tag, category, author, status, claimant, rating, podcast, language, year, month } = { q: null, sort: 'asc', tag: [], @@ -11,6 +11,8 @@ class Filters { status: 'all', podcast: [], language: 'all', + year: null, + month: null, }, ) { this.q = q; @@ -23,6 +25,8 @@ class Filters { this.podcast = podcast; this.language = language; this.rating = rating; + this.year = year; + this.month = month; } } diff --git a/studio/src/utils/getUrlParams.js b/studio/src/utils/getUrlParams.js index 3443ae4b7..4f900c171 100644 --- a/studio/src/utils/getUrlParams.js +++ b/studio/src/utils/getUrlParams.js @@ -1,5 +1,5 @@ function getUrlParams(query, filters) { - const keys = filters ? filters : ['page', 'limit', 'q', 'sort']; + const keys = filters ? filters : ['page', 'limit', 'q', 'sort','date']; const params = { sort: 'desc', limit: 10, @@ -18,7 +18,7 @@ function getUrlParams(query, filters) { ) { const val = query.getAll(key).map((v) => parseInt(v)); params[key] = val; - } else if (key === 'sort' || key === 'q' || key === 'status' || key === 'language') { + } else if (key === 'sort' || key === 'q' || key === 'status' || key === 'language' || key === 'date') { params[key] = query.get(key); } else { params[key] = parseInt(query.get(key));