diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index e5c43aad4..30baa65a3 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -81,6 +81,9 @@ type User { input _UserFilter { AND: [_UserFilter!] OR: [_UserFilter!] + name_contains: String + about_contains: String + slug_contains: String id: ID id_not: ID id_in: [ID!] diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js index 188336572..8f693cfd3 100644 --- a/backend/src/seed/seed-db.js +++ b/backend/src/seed/seed-db.js @@ -683,6 +683,13 @@ import Factory from './factories' to: 'o3', }), ]) + + await Promise.all( + [...Array(30).keys()].map(i => { + return f.create('User') + }), + ) + /* eslint-disable-next-line no-console */ console.log('Seeded Data...') process.exit(0) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 4096f3453..467a9a2ee 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -192,7 +192,19 @@ "name": "Organisationen" }, "users": { - "name": "Benutzer" + "name": "Benutzer", + "form": { + "placeholder": "E-Mail, Name oder Beschreibung" + }, + "table": { + "columns": { + "name": "Name", + "slug": "Slug", + "role": "Rolle", + "createdAt": "Erstellt am" + } + }, + "empty": "Keine Benutzer gefunden" }, "pages": { "name": "Seiten" diff --git a/webapp/locales/en.json b/webapp/locales/en.json index e41192387..edd2c6dc6 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -193,7 +193,19 @@ "name": "Organizations" }, "users": { - "name": "Users" + "name": "Users", + "form": { + "placeholder": "E-Mail, name or description" + }, + "table": { + "columns": { + "name": "Name", + "slug": "Slug", + "role": "Role", + "createdAt": "Created at" + } + }, + "empty": "No users found" }, "pages": { "name": "Pages" diff --git a/webapp/package.json b/webapp/package.json index 1f9119724..7d8b6054a 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -62,6 +62,7 @@ "date-fns": "2.0.0-beta.2", "express": "~4.17.1", "graphql": "~14.4.2", + "isemail": "^3.2.0", "jsonwebtoken": "~8.5.1", "linkify-it": "~2.2.0", "nuxt": "~2.8.1", diff --git a/webapp/pages/admin.vue b/webapp/pages/admin.vue index c9e48ca65..4d498dc9b 100644 --- a/webapp/pages/admin.vue +++ b/webapp/pages/admin.vue @@ -24,11 +24,10 @@ export default { name: this.$t('admin.dashboard.name'), path: `/admin`, }, - // TODO implement - /* { + { name: this.$t('admin.users.name'), - path: `/admin/users` - }, */ + path: `/admin/users`, + }, // TODO implement /* { name: this.$t('admin.organizations.name'), diff --git a/webapp/pages/admin/users.spec.js b/webapp/pages/admin/users.spec.js new file mode 100644 index 000000000..e6b84cad9 --- /dev/null +++ b/webapp/pages/admin/users.spec.js @@ -0,0 +1,70 @@ +import { mount, createLocalVue } from '@vue/test-utils' +import Users from './users.vue' +import Styleguide from '@human-connection/styleguide' + +const localVue = createLocalVue() + +localVue.use(Styleguide) + +describe('Users', () => { + let wrapper + let Wrapper + let mocks + + beforeEach(() => { + mocks = { + $t: jest.fn(), + $apollo: { + loading: false, + }, + } + }) + + describe('mount', () => { + Wrapper = () => { + return mount(Users, { + mocks, + localVue, + }) + } + + it('renders', () => { + wrapper = Wrapper() + expect(wrapper.is('div')).toBe(true) + }) + + describe('search', () => { + let searchAction + beforeEach(() => { + searchAction = (wrapper, { query }) => { + wrapper.find('input').setValue(query) + wrapper.find('form').trigger('submit') + return wrapper + } + }) + + describe('query looks like an email address', () => { + it('searches users for exact email address', async () => { + const wrapper = await searchAction(Wrapper(), { query: 'email@example.org' }) + expect(wrapper.vm.email).toEqual('email@example.org') + expect(wrapper.vm.filter).toBe(null) + }) + }) + + describe('query is just text', () => { + it('tries to find matching users by `name`, `slug` or `about`', async () => { + const wrapper = await searchAction(await Wrapper(), { query: 'Find me' }) + const expected = { + OR: [ + { name_contains: 'Find me' }, + { slug_contains: 'Find me' }, + { about_contains: 'Find me' }, + ], + } + expect(wrapper.vm.email).toBe(null) + expect(wrapper.vm.filter).toEqual(expected) + }) + }) + }) + }) +}) diff --git a/webapp/pages/admin/users.vue b/webapp/pages/admin/users.vue index 90f6d598d..0d737cfc0 100644 --- a/webapp/pages/admin/users.vue +++ b/webapp/pages/admin/users.vue @@ -1,15 +1,173 @@ diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 27f6dc033..d3d4f2639 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -6047,6 +6047,13 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isemail@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c" + integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg== + dependencies: + punycode "2.x.x" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -9173,16 +9180,16 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= +punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"