mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-03-01 12:44:37 +00:00
refactor(package/ui): os-card (#9246)
This commit is contained in:
parent
daafde24b0
commit
4f4f2e4696
@ -3,5 +3,5 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
defineStep('I can visit the post page', () => {
|
||||
cy.contains('Fake news').click()
|
||||
cy.location('pathname').should('contain', '/post')
|
||||
.get('.base-card .title').should('contain', 'Fake news')
|
||||
.get('.os-card .title').should('contain', 'Fake news')
|
||||
})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('I click on "Report Post" from the content menu of the post', () => {
|
||||
cy.contains('.base-card', 'The Truth about the Holocaust')
|
||||
cy.contains('.os-card', 'The Truth about the Holocaust')
|
||||
.find('[data-test="content-menu-button"]')
|
||||
.click()
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('the post was saved successfully', () => {
|
||||
cy.task('getValue', 'lastPost').then(lastPost => {
|
||||
cy.get('.base-card > .title').should('contain', lastPost.title)
|
||||
cy.get('.os-card .title').should('contain', lastPost.title)
|
||||
cy.get('.content').should('contain', lastPost.content)
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('the first image should not be displayed anymore', () => {
|
||||
cy.get('.hero-image')
|
||||
.children()
|
||||
.get('.hero-image > .image')
|
||||
cy.get('.os-card__hero-image > .image')
|
||||
.should('have.length', 1)
|
||||
.and('have.attr', 'src')
|
||||
})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('the post was saved successfully with the {string} teaser image', condition => {
|
||||
cy.get('.base-card > .title')
|
||||
cy.get('.os-card .title')
|
||||
.should('contain', condition === 'updated' ? 'to be updated' : 'new post')
|
||||
.get('.content')
|
||||
.should('contain', condition === 'updated' ? 'successfully updated' : 'new post content')
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('the {string} post was saved successfully without a teaser image', condition => {
|
||||
cy.get(".base-card > .title")
|
||||
cy.get(".os-card > .title")
|
||||
.should("contain", condition === 'updated' ? 'to be updated' : 'new post')
|
||||
.get(".content")
|
||||
.should("contain", condition === 'updated' ? 'successfully updated' : 'new post content')
|
||||
.get('.post-page')
|
||||
.should('exist')
|
||||
.get('.hero-image > .image')
|
||||
.get('.os-card__hero-image > .image')
|
||||
.should('not.exist')
|
||||
})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('the post shows up on the newsfeed at position {int}', index => {
|
||||
const selector = `.post-teaser:nth-child(${index}) > .base-card`
|
||||
const selector = `.post-teaser:nth-child(${index}) > .os-card`
|
||||
cy.get(selector).should('contain', 'previously created post')
|
||||
cy.get(selector).should('contain', 'with some content')
|
||||
})
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('I should not see {string} button', button => {
|
||||
cy.get('.base-card .action-buttons')
|
||||
cy.get('.os-card .action-buttons')
|
||||
.should('have.length', 1)
|
||||
})
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('I should see the {string} button', button => {
|
||||
cy.get('.base-card .action-buttons button')
|
||||
cy.get('.os-card .action-buttons button')
|
||||
.should('contain', button)
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('they should not see the comment form', () => {
|
||||
cy.get('.base-card').children().should('not.have.class', 'comment-form')
|
||||
cy.get('.os-card').children().should('not.have.class', 'comment-form')
|
||||
})
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('the list of posts of this user is empty', () => {
|
||||
cy.get('.base-card').not('.post-link')
|
||||
cy.get('.os-card').not('.post-link')
|
||||
cy.get('.main-container').find('.ds-space.hc-empty')
|
||||
})
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('I cannot upload a picture', () => {
|
||||
cy.get('.base-card')
|
||||
cy.get('.os-card')
|
||||
.children()
|
||||
.should('not.have.id', 'customdropzone')
|
||||
.should('have.class', 'profile-avatar')
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||
|
||||
defineStep('I get removed from his follower collection', () => {
|
||||
cy.get('.base-card')
|
||||
cy.get('.os-card')
|
||||
.not('.post-link')
|
||||
cy.get('.main-container')
|
||||
.contains('.base-card','is not followed by anyone')
|
||||
.contains('.os-card','is not followed by anyone')
|
||||
})
|
||||
|
||||
@ -81,10 +81,10 @@ Phase 0: ██████████ 100% (6/6 Aufgaben) ✅
|
||||
Phase 1: ██████████ 100% (6/6 Aufgaben) ✅
|
||||
Phase 2: ██████████ 100% (26/26 Aufgaben) ✅
|
||||
Phase 3: ██████████ 100% (24/24 Aufgaben) ✅ - Webapp-Integration komplett
|
||||
Phase 4: ████░░░░░░ 35% (6/17 Aufgaben) - OsButton ✅, OsIcon ✅, System-Icons ✅, BaseIcon→OsIcon Migration ✅, OsSpinner ✅, Spinner Webapp-Migration ✅
|
||||
Phase 4: █████░░░░░ 47% (8/17 Aufgaben) - OsButton ✅, OsIcon ✅, System-Icons ✅, BaseIcon→OsIcon Migration ✅, OsSpinner ✅, Spinner Webapp-Migration ✅, OsCard ✅, BaseCard→OsCard Migration ✅
|
||||
Phase 5: ░░░░░░░░░░ 0% (0/7 Aufgaben)
|
||||
───────────────────────────────────────
|
||||
Gesamt: ████████░░ 79% (68/86 Aufgaben)
|
||||
Gesamt: ████████░░ 81% (70/86 Aufgaben)
|
||||
```
|
||||
|
||||
### Katalogisierung (Details in KATALOG.md)
|
||||
@ -142,6 +142,23 @@ OsSpinner:
|
||||
├─ vue-compat: ✅ h() Render-Function mit isVue2
|
||||
└─ webapp: ✅ 4 Spinner migriert (DsSpinner + LoadingSpinner → OsSpinner)
|
||||
|
||||
BaseCard → OsCard Webapp-Migration: ✅
|
||||
├─ ~30 Webapp-Dateien: <base-card> → <os-card> (lokale Imports)
|
||||
├─ 3 Template-Dateien: #imageColumn/#topMenu Slots → inline Layout mit --columns CSS
|
||||
├─ 16 Spec-Dateien: wrapper.classes('base-card') → wrapper.classes('os-card')
|
||||
├─ 4 Story-Dateien: <base-card> → <os-card> mit Import
|
||||
├─ 12 Cypress E2E-Dateien: .base-card → .os-card Selektoren
|
||||
├─ 2 Cypress-Dateien: .hero-image → .os-card__hero-image
|
||||
├─ BaseCard.vue Komponente gelöscht
|
||||
├─ base-components.js Plugin gelöscht (keine Base*.vue mehr)
|
||||
├─ nuxt.config.js, maintenance config, testSetup.js bereinigt
|
||||
├─ main.scss: .os-card Regeln (title, ds-section, hero-image, --columns Layout)
|
||||
├─ CSS Fixes: Tailwind p-6 Override (!important), outline statt border (highlight),
|
||||
│ child selectors → descendant selectors (hero-image content wrapper)
|
||||
├─ ContributionForm: Media-Query Selektoren auf .os-card__content korrigiert
|
||||
├─ ProfileList: .profile-list.os-card Spezifität erhöht (0,3,0 vs 0,2,0)
|
||||
└─ 0 <base-card> Template-Nutzungen verbleibend
|
||||
|
||||
DsSpinner/LoadingSpinner → OsSpinner Webapp-Migration: ✅
|
||||
├─ ImageUploader.vue: LoadingSpinner → OsSpinner (size="lg")
|
||||
├─ pages/profile: ds-spinner → os-spinner (size="lg")
|
||||
@ -166,11 +183,30 @@ BaseIcon → OsIcon Webapp-Migration: ✅
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
**Letzte Aktualisierung:** 2026-02-18 (Session 24)
|
||||
**Letzte Aktualisierung:** 2026-02-19 (Session 25)
|
||||
|
||||
**Aktuelle Phase:** Phase 4 - OsIcon ✅, BaseIcon → OsIcon Migration ✅, OsSpinner ✅, Spinner Webapp-Migration ✅
|
||||
**Aktuelle Phase:** Phase 4 - OsIcon ✅, BaseIcon → OsIcon Migration ✅, OsSpinner ✅, Spinner Webapp-Migration ✅, OsCard ✅, BaseCard → OsCard Migration ✅
|
||||
|
||||
**Zuletzt abgeschlossen (Session 24 - OsSpinner Webapp-Migration + Refactoring):**
|
||||
**Zuletzt abgeschlossen (Session 25 - BaseCard → OsCard Webapp-Migration):**
|
||||
- [x] ~30 Webapp-Dateien: `<base-card>` → `<os-card>` mit lokalen Imports
|
||||
- [x] 3 Template-Dateien mit #imageColumn/#topMenu Slots → inline Layout (LoginForm, RegistrationSlider, password-reset)
|
||||
- [x] CSS: `.os-card.--columns` Layout in main.scss (flex, image-column, content-column, top-menu, responsive)
|
||||
- [x] 16 Spec-Dateien: `wrapper.classes('base-card')` → `wrapper.classes('os-card')`
|
||||
- [x] 4 Story-Dateien: `<base-card>` → `<os-card>` mit OsCard-Import
|
||||
- [x] 12 Cypress E2E Step-Definitions: `.base-card` → `.os-card` Selektoren
|
||||
- [x] 2 Cypress-Dateien: `.hero-image` → `.os-card__hero-image`
|
||||
- [x] BaseCard.vue Komponente gelöscht
|
||||
- [x] `base-components.js` Plugin gelöscht (keine Base*.vue Komponenten mehr)
|
||||
- [x] Plugin-Referenzen entfernt: nuxt.config.js, nuxt.config.maintenance.js, testSetup.js
|
||||
- [x] main.scss bereinigt: `.base-card > .ds-section` entfernt, `.os-card` Regeln hinzugefügt
|
||||
- [x] CSS-Fixes: Tailwind `p-6` Override (`!important`), `outline` statt `border` (highlight), child → descendant selectors
|
||||
- [x] ContributionForm: Media-Query Selektoren auf `.os-card__content > .buttons-footer` korrigiert
|
||||
- [x] ProfileList: Spezifität `.profile-list.os-card` erhöht (0,3,0 vs 0,2,0)
|
||||
- [x] OsCard highlight Tests: `border` → `outline-1` (twMerge), Testnamen aktualisiert
|
||||
- [x] Kleinere Verbesserungen: SocialMedia Props typisiert, LoginForm querySelector statt fragiler DOM-Traversierung, redundante `<client-only>` entfernt, NotificationsTable optional chaining
|
||||
- [x] `hasBaseCard` Property verbleibt in 4 Dateien (rein semantisch, kein Komponentenbezug)
|
||||
|
||||
**Zuvor abgeschlossen (Session 24 - OsSpinner Webapp-Migration + Refactoring):**
|
||||
- [x] OsButton refactored: nutzt `h(OsSpinner, { 'aria-hidden': 'true' })` statt Inline-SVG
|
||||
- [x] OsSpinner: Decorative-Modus (`aria-hidden="true"` unterdrückt role/aria-label)
|
||||
- [x] `ButtonSize` Type exportiert (sm/md/lg/xl), `types.d.ts` Kommentar aktualisiert
|
||||
@ -263,8 +299,8 @@ BaseIcon → OsIcon Webapp-Migration: ✅
|
||||
|
||||
**Nächste Schritte:**
|
||||
- [x] OsSpinner Webapp-Migration (DsSpinner + LoadingSpinner → OsSpinner) ✅
|
||||
- [ ] OsCard Komponente (vereint DsCard + BaseCard)
|
||||
- [ ] Weitere Tier 1 Komponenten
|
||||
- [x] OsCard Komponente + BaseCard → OsCard Webapp-Migration ✅
|
||||
- [ ] Weitere Tier 2 Komponenten (OsModal, OsDropdown, OsAvatar, OsInput)
|
||||
- [ ] Browser-Fehler untersuchen: `TypeError: Cannot read properties of undefined (reading 'heartO')` (ocelotIcons undefined im Browser trotz korrekter Webpack-Aliase)
|
||||
|
||||
**Manuelle Setup-Aufgaben (außerhalb Code):**
|
||||
@ -519,7 +555,7 @@ Jeder migrierte Button muss manuell geprüft werden: Normal, Hover, Focus, Activ
|
||||
- [x] OsSpinner (vereint DsSpinner + LoadingSpinner) ✅ OsButton nutzt OsSpinner als Komponente
|
||||
- [x] OsSpinner Webapp-Migration ✅ 4 Spinner migriert, LoadingSpinner gelöscht, Admin ApolloQuery→$apollo.loading
|
||||
- [x] OsButton (vereint DsButton + BaseButton) ✅ Entwickelt in Phase 2
|
||||
- [ ] OsCard (vereint DsCard + BaseCard)
|
||||
- [x] OsCard (vereint DsCard + BaseCard) ✅ Webapp-Migration abgeschlossen, BaseCard gelöscht
|
||||
|
||||
**Tier 2: Layout & Feedback**
|
||||
- [ ] OsModal (Basis: DsModal)
|
||||
@ -1629,6 +1665,12 @@ Bei der Migration werden:
|
||||
| 2026-02-18 | **Admin Spinner Fix** | `<ApolloQuery>` → `apollo`-Option + `$apollo.loading`; SSR-Prefetch verhinderte Loading-State im Client |
|
||||
| 2026-02-18 | **filterStatistics Fix** | `delete data.__typename` → Destructuring `{ __typename, ...rest }` (keine Mutation des Originalobjekts) |
|
||||
| 2026-02-18 | **infinite-loading Spinner-Slot** | OsSpinner im `spinner`-Slot von vue-infinite-loading in 3 Seiten (index, profile, groups); einheitliches Spinner-Design |
|
||||
| 2026-02-19 | **BaseCard → OsCard Migration** | ~30 Webapp-Dateien: `<base-card>` → `<os-card>` mit lokalen Imports; CSS-Fixes für Tailwind p-6 Override, outline highlight, child→descendant selectors |
|
||||
| 2026-02-19 | **#imageColumn/#topMenu inline** | LoginForm, RegistrationSlider, password-reset: BaseCard-Slots → inline Layout mit `.os-card.--columns` CSS in main.scss |
|
||||
| 2026-02-19 | **Tests & Stories migriert** | 16 Spec-Dateien, 4 Story-Dateien, 12+2 Cypress E2E Step-Definitions: base-card → os-card Selektoren |
|
||||
| 2026-02-19 | **BaseCard gelöscht** | BaseCard.vue Komponente + base-components.js Plugin entfernt; nuxt.config, maintenance config, testSetup bereinigt |
|
||||
| 2026-02-19 | **CSS-Fixes** | ContributionForm Media-Query Selektoren, ProfileList Spezifität, InternalPage $space-small, OsCard highlight outline-1 Tests |
|
||||
| 2026-02-19 | **Code-Quality** | SocialMedia Props typisiert, LoginForm querySelector, redundante client-only entfernt, NotificationsTable optional chaining, HashtagsFilter doppeltes Mounting |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -144,7 +144,7 @@
|
||||
"size-limit": [
|
||||
{
|
||||
"path": "dist/index.mjs",
|
||||
"limit": "15 kB",
|
||||
"limit": "20 kB",
|
||||
"brotli": true
|
||||
},
|
||||
{
|
||||
|
||||
191
packages/ui/src/components/OsCard/OsCard.spec.ts
Normal file
191
packages/ui/src/components/OsCard/OsCard.spec.ts
Normal file
@ -0,0 +1,191 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import OsCard from './OsCard.vue'
|
||||
|
||||
describe('osCard', () => {
|
||||
describe('rendering', () => {
|
||||
it('renders as div element by default', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect((wrapper.element as HTMLElement).tagName).toBe('DIV')
|
||||
})
|
||||
|
||||
it('renders default slot content', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
slots: { default: '<p>Card content</p>' },
|
||||
})
|
||||
|
||||
expect(wrapper.find('p').text()).toBe('Card content')
|
||||
})
|
||||
|
||||
it('renders without content', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
expect(wrapper.text()).toBe('')
|
||||
})
|
||||
})
|
||||
|
||||
describe('as prop', () => {
|
||||
it('renders as article when as="article"', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
props: { as: 'article' },
|
||||
})
|
||||
|
||||
expect((wrapper.element as HTMLElement).tagName).toBe('ARTICLE')
|
||||
})
|
||||
|
||||
it('renders as section when as="section"', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
props: { as: 'section' },
|
||||
})
|
||||
|
||||
expect((wrapper.element as HTMLElement).tagName).toBe('SECTION')
|
||||
})
|
||||
|
||||
it('renders as aside when as="aside"', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
props: { as: 'aside' },
|
||||
})
|
||||
|
||||
expect((wrapper.element as HTMLElement).tagName).toBe('ASIDE')
|
||||
})
|
||||
})
|
||||
|
||||
describe('css', () => {
|
||||
it('has os-card class', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect(wrapper.classes()).toContain('os-card')
|
||||
})
|
||||
|
||||
it('has padding when no heroImage slot', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect(wrapper.classes()).toContain('p-6')
|
||||
})
|
||||
|
||||
it('merges custom classes', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
attrs: { class: 'my-custom-class' },
|
||||
})
|
||||
|
||||
expect(wrapper.classes()).toContain('os-card')
|
||||
expect(wrapper.classes()).toContain('my-custom-class')
|
||||
})
|
||||
|
||||
it('passes through attributes', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
attrs: { 'data-testid': 'my-card' },
|
||||
})
|
||||
|
||||
expect(wrapper.attributes('data-testid')).toBe('my-card')
|
||||
})
|
||||
})
|
||||
|
||||
describe('highlight', () => {
|
||||
it('does not have outline class by default', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect(wrapper.classes()).not.toContain('outline-1')
|
||||
})
|
||||
|
||||
it('adds outline class when highlight is true', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
props: { highlight: true },
|
||||
})
|
||||
|
||||
expect(wrapper.classes()).toContain('outline-1')
|
||||
})
|
||||
|
||||
it('does not add outline class when highlight is false', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
props: { highlight: false },
|
||||
})
|
||||
|
||||
expect(wrapper.classes()).not.toContain('outline-1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('heroImage slot', () => {
|
||||
const heroSlots = {
|
||||
heroImage: '<img src="/test.jpg" alt="Hero" />',
|
||||
default: '<p>Content</p>',
|
||||
}
|
||||
|
||||
it('renders heroImage slot content', () => {
|
||||
const wrapper = mount(OsCard, { slots: heroSlots })
|
||||
|
||||
expect(wrapper.find('img').exists()).toBe(true)
|
||||
expect(wrapper.find('img').attributes('alt')).toBe('Hero')
|
||||
})
|
||||
|
||||
it('wraps heroImage in os-card__hero-image div', () => {
|
||||
const wrapper = mount(OsCard, { slots: heroSlots })
|
||||
|
||||
const heroDiv = wrapper.find('.os-card__hero-image')
|
||||
|
||||
expect(heroDiv.exists()).toBe(true)
|
||||
expect(heroDiv.find('img').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('wraps default content in os-card__content div', () => {
|
||||
const wrapper = mount(OsCard, { slots: heroSlots })
|
||||
|
||||
const contentDiv = wrapper.find('.os-card__content')
|
||||
|
||||
expect(contentDiv.exists()).toBe(true)
|
||||
expect(contentDiv.find('p').text()).toBe('Content')
|
||||
})
|
||||
|
||||
it('does not have padding on card when heroImage is present', () => {
|
||||
const wrapper = mount(OsCard, { slots: heroSlots })
|
||||
|
||||
expect(wrapper.classes()).not.toContain('p-6')
|
||||
})
|
||||
|
||||
it('content wrapper has padding when heroImage is present', () => {
|
||||
const wrapper = mount(OsCard, { slots: heroSlots })
|
||||
|
||||
expect(wrapper.find('.os-card__content').classes()).toContain('p-6')
|
||||
})
|
||||
|
||||
it('does not create wrapper divs without heroImage slot', () => {
|
||||
const wrapper = mount(OsCard, {
|
||||
slots: { default: '<p>Content</p>' },
|
||||
})
|
||||
|
||||
expect(wrapper.find('.os-card__hero-image').exists()).toBe(false)
|
||||
expect(wrapper.find('.os-card__content').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('renders heroImage before content', () => {
|
||||
const wrapper = mount(OsCard, { slots: heroSlots })
|
||||
|
||||
const heroImage = wrapper.find('.os-card__hero-image')
|
||||
const content = wrapper.find('.os-card__content')
|
||||
|
||||
expect(heroImage.exists()).toBe(true)
|
||||
expect(content.exists()).toBe(true)
|
||||
expect(
|
||||
heroImage.element.compareDocumentPosition(content.element) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING,
|
||||
).not.toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('keyboard accessibility', () => {
|
||||
it('is not focusable (non-interactive element)', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect(wrapper.attributes('tabindex')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('has no interactive role', () => {
|
||||
const wrapper = mount(OsCard)
|
||||
|
||||
expect(wrapper.attributes('role')).toBeUndefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
161
packages/ui/src/components/OsCard/OsCard.stories.ts
Normal file
161
packages/ui/src/components/OsCard/OsCard.stories.ts
Normal file
@ -0,0 +1,161 @@
|
||||
import { computed } from 'vue'
|
||||
|
||||
import OsCard from './OsCard.vue'
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
const HERO_SVG =
|
||||
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='200'%3E%3Crect fill='%234a5a9e' width='400' height='200'/%3E%3Ctext x='200' y='105' text-anchor='middle' fill='white' font-size='20' font-family='sans-serif'%3EHero Image%3C/text%3E%3C/svg%3E"
|
||||
|
||||
const meta: Meta<typeof OsCard> = {
|
||||
title: 'Components/OsCard',
|
||||
component: OsCard,
|
||||
tags: ['autodocs'],
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof OsCard>
|
||||
|
||||
interface PlaygroundArgs {
|
||||
as: string
|
||||
highlight: boolean
|
||||
heroImage: boolean
|
||||
content: string
|
||||
}
|
||||
|
||||
export const Playground: StoryObj<PlaygroundArgs> = {
|
||||
argTypes: {
|
||||
as: {
|
||||
control: 'select',
|
||||
options: ['div', 'article', 'section', 'aside'],
|
||||
},
|
||||
highlight: {
|
||||
control: 'boolean',
|
||||
},
|
||||
heroImage: {
|
||||
control: 'boolean',
|
||||
},
|
||||
content: {
|
||||
control: 'text',
|
||||
},
|
||||
},
|
||||
args: {
|
||||
as: 'div',
|
||||
highlight: false,
|
||||
heroImage: false,
|
||||
content: 'This is a card with customizable props. Try toggling the controls below.',
|
||||
},
|
||||
render: (args) => ({
|
||||
components: { OsCard },
|
||||
setup() {
|
||||
const cardProps = computed(() => ({
|
||||
as: args.as,
|
||||
highlight: args.highlight,
|
||||
}))
|
||||
const showHero = computed(() => args.heroImage)
|
||||
const content = computed(() => args.content)
|
||||
return { cardProps, showHero, content, HERO_SVG }
|
||||
},
|
||||
template: `
|
||||
<div style="max-width: 400px">
|
||||
<OsCard v-bind="cardProps">
|
||||
<template v-if="showHero" #heroImage>
|
||||
<img :src="HERO_SVG" alt="Hero placeholder" style="display: block; width: 100%; height: auto" />
|
||||
</template>
|
||||
<p style="margin: 0">{{ content }}</p>
|
||||
</OsCard>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
|
||||
export const SimpleWrapper: Story = {
|
||||
render: () => ({
|
||||
components: { OsCard },
|
||||
template: `
|
||||
<div data-testid="simple-wrapper" class="flex flex-col gap-4" style="max-width: 400px">
|
||||
<OsCard>
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Card Title</h3>
|
||||
<p style="margin: 0; color: #666">Some card content goes here. Cards provide a contained surface for related information.</p>
|
||||
</OsCard>
|
||||
<OsCard>
|
||||
<p style="margin: 0">A minimal card with just text.</p>
|
||||
</OsCard>
|
||||
<OsCard>
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Another Card</h3>
|
||||
<p style="margin: 0; color: #666">Cards stack naturally in a flex column layout.</p>
|
||||
</OsCard>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
|
||||
export const CustomClass: Story = {
|
||||
render: () => ({
|
||||
components: { OsCard },
|
||||
template: `
|
||||
<div data-testid="custom-class" style="max-width: 400px">
|
||||
<OsCard class="text-center">
|
||||
<p style="margin: 0">Centered content via custom class.</p>
|
||||
</OsCard>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
|
||||
export const Highlight: Story = {
|
||||
render: () => ({
|
||||
components: { OsCard },
|
||||
template: `
|
||||
<div data-testid="highlight" class="flex flex-col gap-4" style="max-width: 400px">
|
||||
<OsCard :highlight="true">
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Pinned Post</h3>
|
||||
<p style="margin: 0; color: #666">This card is highlighted with a colored border, used for pinned or featured content.</p>
|
||||
</OsCard>
|
||||
<OsCard>
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Normal Post</h3>
|
||||
<p style="margin: 0; color: #666">This card has no highlight for comparison.</p>
|
||||
</OsCard>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
|
||||
export const HeroImage: Story = {
|
||||
render: () => ({
|
||||
components: { OsCard },
|
||||
setup() {
|
||||
return { HERO_SVG }
|
||||
},
|
||||
template: `
|
||||
<div data-testid="hero-image" class="flex flex-col gap-4" style="max-width: 400px">
|
||||
<OsCard as="article" :highlight="true">
|
||||
<template #heroImage>
|
||||
<img
|
||||
:src="HERO_SVG"
|
||||
alt="Hero placeholder"
|
||||
style="display: block; width: 100%; height: auto"
|
||||
/>
|
||||
</template>
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Pinned Post with Image</h3>
|
||||
<p style="margin: 0; color: #666">Combines hero image, highlight border, and article semantics.</p>
|
||||
</OsCard>
|
||||
<OsCard>
|
||||
<template #heroImage>
|
||||
<img
|
||||
:src="HERO_SVG"
|
||||
alt="Hero placeholder"
|
||||
style="display: block; width: 100%; height: auto"
|
||||
/>
|
||||
</template>
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Post with Hero Image</h3>
|
||||
<p style="margin: 0; color: #666">The image spans the full card width. Content below has its own padding.</p>
|
||||
</OsCard>
|
||||
<OsCard>
|
||||
<h3 style="margin: 0 0 8px; font-weight: 600">Card without Image</h3>
|
||||
<p style="margin: 0; color: #666">A regular card for comparison.</p>
|
||||
</OsCard>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
}
|
||||
88
packages/ui/src/components/OsCard/OsCard.visual.spec.ts
Normal file
88
packages/ui/src/components/OsCard/OsCard.visual.spec.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { AxeBuilder } from '@axe-core/playwright'
|
||||
import { expect, test } from '@playwright/test'
|
||||
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
const STORY_URL = '/iframe.html?id=components-oscard'
|
||||
const STORY_ROOT = '#storybook-root'
|
||||
|
||||
async function waitForReady(page: Page) {
|
||||
await page.evaluate(async () => document.fonts.ready)
|
||||
}
|
||||
|
||||
async function checkA11y(page: Page) {
|
||||
const results = await new AxeBuilder({ page }).include(STORY_ROOT).analyze()
|
||||
|
||||
expect(results.violations).toEqual([])
|
||||
}
|
||||
|
||||
test.describe('OsCard keyboard accessibility', () => {
|
||||
test('card is not focusable (non-interactive element)', async ({ page }) => {
|
||||
await page.goto(`${STORY_URL}--simple-wrapper&viewMode=story`)
|
||||
const root = page.locator(STORY_ROOT)
|
||||
await root.waitFor()
|
||||
|
||||
const cards = root.locator('.os-card')
|
||||
const count = await cards.count()
|
||||
|
||||
expect(count).toBeGreaterThan(0)
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
await expect(cards.nth(i)).not.toHaveAttribute('tabindex')
|
||||
await expect(cards.nth(i)).not.toHaveAttribute('role')
|
||||
}
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
for (let i = 0; i < count; i++) {
|
||||
await expect(cards.nth(i)).not.toBeFocused()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('OsCard visual regression', () => {
|
||||
test('simple wrapper', async ({ page }) => {
|
||||
await page.goto(`${STORY_URL}--simple-wrapper&viewMode=story`)
|
||||
const root = page.locator(STORY_ROOT)
|
||||
await root.waitFor()
|
||||
await waitForReady(page)
|
||||
|
||||
await expect(root.locator('[data-testid="simple-wrapper"]')).toHaveScreenshot(
|
||||
'simple-wrapper.png',
|
||||
)
|
||||
|
||||
await checkA11y(page)
|
||||
})
|
||||
|
||||
test('custom class', async ({ page }) => {
|
||||
await page.goto(`${STORY_URL}--custom-class&viewMode=story`)
|
||||
const root = page.locator(STORY_ROOT)
|
||||
await root.waitFor()
|
||||
await waitForReady(page)
|
||||
|
||||
await expect(root.locator('[data-testid="custom-class"]')).toHaveScreenshot('custom-class.png')
|
||||
|
||||
await checkA11y(page)
|
||||
})
|
||||
|
||||
test('highlight', async ({ page }) => {
|
||||
await page.goto(`${STORY_URL}--highlight&viewMode=story`)
|
||||
const root = page.locator(STORY_ROOT)
|
||||
await root.waitFor()
|
||||
await waitForReady(page)
|
||||
|
||||
await expect(root.locator('[data-testid="highlight"]')).toHaveScreenshot('highlight.png')
|
||||
|
||||
await checkA11y(page)
|
||||
})
|
||||
|
||||
test('hero image', async ({ page }) => {
|
||||
await page.goto(`${STORY_URL}--hero-image&viewMode=story`)
|
||||
const root = page.locator(STORY_ROOT)
|
||||
await root.waitFor()
|
||||
await waitForReady(page)
|
||||
|
||||
await expect(root.locator('[data-testid="hero-image"]')).toHaveScreenshot('hero-image.png')
|
||||
|
||||
await checkA11y(page)
|
||||
})
|
||||
})
|
||||
104
packages/ui/src/components/OsCard/OsCard.vue
Normal file
104
packages/ui/src/components/OsCard/OsCard.vue
Normal file
@ -0,0 +1,104 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, getCurrentInstance, h, isVue2 } from 'vue-demi'
|
||||
|
||||
import { cn } from '#src/utils'
|
||||
|
||||
import type { ClassValue } from 'clsx'
|
||||
import type { PropType } from 'vue-demi'
|
||||
|
||||
const CARD_BASE =
|
||||
'os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)]'
|
||||
|
||||
const HIGHLIGHT_CLASS = 'outline outline-1 outline-[var(--color-warning)]'
|
||||
|
||||
const HERO_IMAGE_CLASS = 'os-card__hero-image overflow-hidden'
|
||||
const CONTENT_CLASS = 'os-card__content p-6'
|
||||
|
||||
/**
|
||||
* Content card container with rounded corners, background, and shadow.
|
||||
* Renders as `<div>` by default. Use `as="article"` for self-contained
|
||||
* content like posts or comments.
|
||||
*
|
||||
* When `heroImage` slot is provided, the card uses a two-section layout:
|
||||
* the hero image spans full width (no padding), followed by padded content.
|
||||
* Without `heroImage`, the card applies padding directly.
|
||||
*
|
||||
* @slot default - Card content
|
||||
* @slot heroImage - Full-width image at the top of the card
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'OsCard',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
/**
|
||||
* HTML element to render as. Use `article` for self-contained content
|
||||
* (posts, comments), `section` for thematic groups, or `div` (default)
|
||||
* for generic containers.
|
||||
*/
|
||||
as: {
|
||||
type: String as PropType<'div' | 'article' | 'section' | 'aside'>,
|
||||
default: 'div',
|
||||
},
|
||||
/**
|
||||
* Adds a colored border to highlight the card (e.g. for pinned posts).
|
||||
* Uses `--color-warning` CSS variable for border color.
|
||||
*/
|
||||
highlight: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props, { slots, attrs }) {
|
||||
/* v8 ignore start -- Vue 2 only */
|
||||
const instance = isVue2 ? getCurrentInstance() : null
|
||||
/* v8 ignore stop */
|
||||
|
||||
return () => {
|
||||
const defaultContent = slots.default?.()
|
||||
const heroImageContent = slots.heroImage?.()
|
||||
const hasHeroImage = heroImageContent && heroImageContent.length > 0
|
||||
|
||||
const cardClass = cn(CARD_BASE, !hasHeroImage && 'p-6', props.highlight && HIGHLIGHT_CLASS)
|
||||
|
||||
const children = hasHeroImage
|
||||
? [
|
||||
h('div', { class: HERO_IMAGE_CLASS }, heroImageContent),
|
||||
h('div', { class: CONTENT_CLASS }, defaultContent),
|
||||
]
|
||||
: defaultContent
|
||||
|
||||
const tag = props.as
|
||||
|
||||
/* v8 ignore start -- Vue 2 branch tested in webapp Jest tests */
|
||||
if (isVue2) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const proxy = instance?.proxy as any
|
||||
const parentClass = proxy?.$vnode?.data?.staticClass || ''
|
||||
const parentDynClass = proxy?.$vnode?.data?.class
|
||||
const parentAttrs = proxy?.$vnode?.data?.attrs || {}
|
||||
|
||||
return h(
|
||||
tag,
|
||||
{
|
||||
class: cn(cardClass, parentClass, parentDynClass),
|
||||
attrs: { ...parentAttrs, ...attrs },
|
||||
},
|
||||
children,
|
||||
)
|
||||
}
|
||||
/* v8 ignore stop */
|
||||
|
||||
const { class: attrClass, ...restAttrs } = attrs as Record<string, unknown>
|
||||
|
||||
return h(
|
||||
tag,
|
||||
{
|
||||
class: cn(cardClass, attrClass as ClassValue),
|
||||
...restAttrs,
|
||||
},
|
||||
children,
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
1
packages/ui/src/components/OsCard/index.ts
Normal file
1
packages/ui/src/components/OsCard/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as OsCard } from './OsCard.vue'
|
||||
@ -18,3 +18,4 @@ export {
|
||||
type SystemIconName,
|
||||
} from './OsIcon'
|
||||
export { OsSpinner, SPINNER_SIZES } from './OsSpinner'
|
||||
export { OsCard } from './OsCard'
|
||||
|
||||
@ -151,7 +151,7 @@ body.dropdown-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.base-card > .ds-section {
|
||||
.os-card > .ds-section {
|
||||
padding: 0;
|
||||
margin: -$space-base;
|
||||
|
||||
@ -160,6 +160,57 @@ body.dropdown-open {
|
||||
}
|
||||
}
|
||||
|
||||
.os-card {
|
||||
> .title,
|
||||
> .content-column > .title {
|
||||
font-size: $font-size-large;
|
||||
margin-bottom: $space-x-small;
|
||||
}
|
||||
|
||||
> .os-card__hero-image > .image {
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
&.--columns {
|
||||
display: flex;
|
||||
|
||||
> .image-column {
|
||||
flex-basis: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-right: $space-base;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
> .content-column {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
|
||||
> .top-menu {
|
||||
position: absolute;
|
||||
top: $space-small;
|
||||
left: $space-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 565px) {
|
||||
.os-card.--columns {
|
||||
flex-direction: column;
|
||||
|
||||
> .image-column {
|
||||
padding-right: 0;
|
||||
margin-bottom: $space-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[class$='menu-popover'] {
|
||||
min-width: 130px;
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<base-card v-if="isUnavailable" class="comment-card">
|
||||
<os-card as="article" v-if="isUnavailable" class="comment-card">
|
||||
<p>
|
||||
<os-icon :icon="icons.ban" />
|
||||
{{ $t('comment.content.unavailable-placeholder') }}
|
||||
</p>
|
||||
</base-card>
|
||||
<base-card v-else :class="commentClass" :id="anchor">
|
||||
</os-card>
|
||||
<os-card as="article" v-else :class="commentClass" :id="anchor">
|
||||
<header class="header">
|
||||
<user-teaser :user="comment.author" :date-time="comment.createdAt">
|
||||
<template v-if="wasEdited" #dateTime>
|
||||
@ -70,11 +70,11 @@
|
||||
</template>
|
||||
</os-button>
|
||||
</div>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { COMMENT_MAX_UNTRUNCATED_LENGTH, COMMENT_TRUNCATE_TO_LENGTH } from '~/constants/comment'
|
||||
@ -89,6 +89,7 @@ import scrollToAnchor from '~/mixins/scrollToAnchor.js'
|
||||
export default {
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
UserTeaser,
|
||||
ContentMenu,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<ds-form v-model="form" @submit="handleSubmit" class="comment-form">
|
||||
<template #default="{ errors }">
|
||||
<base-card>
|
||||
<os-card>
|
||||
<hc-editor ref="editor" :users="users" :value="form.content" @input="updateEditorContent" />
|
||||
<div class="buttons">
|
||||
<os-button
|
||||
@ -26,13 +26,13 @@
|
||||
{{ $t('post.comment.submit') }}
|
||||
</os-button>
|
||||
</div>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
</ds-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import HcEditor from '~/components/Editor/Editor'
|
||||
import { COMMENT_MIN_LENGTH } from '~/constants/comment'
|
||||
@ -42,6 +42,7 @@ import CommentMutations from '~/graphql/CommentMutations'
|
||||
export default {
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
HcEditor,
|
||||
},
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
@submit="submit"
|
||||
>
|
||||
<template #default="{ errors }">
|
||||
<base-card>
|
||||
<os-card>
|
||||
<template #heroImage>
|
||||
<img
|
||||
v-if="formData.image"
|
||||
@ -196,13 +196,13 @@
|
||||
</os-button>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
</ds-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import gql from 'graphql-tag'
|
||||
import { mapGetters } from 'vuex'
|
||||
@ -224,6 +224,7 @@ export default {
|
||||
Editor,
|
||||
ImageUploader,
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
PageParamsLink,
|
||||
},
|
||||
@ -540,15 +541,18 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.contribution-form > .base-card {
|
||||
.contribution-form > .os-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .hero-image {
|
||||
> .os-card__hero-image {
|
||||
position: relative;
|
||||
max-height: $size-image-max-height;
|
||||
overflow: hidden;
|
||||
|
||||
> .image {
|
||||
max-height: $size-image-max-height;
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,41 +560,46 @@ export default {
|
||||
filter: blur($blur-radius);
|
||||
}
|
||||
|
||||
> .ds-form-item {
|
||||
margin: 0;
|
||||
}
|
||||
> .os-card__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .ds-chip {
|
||||
align-self: flex-end;
|
||||
margin: $space-xx-small 0 $space-base;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
> .select-field {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
> .buttons-footer {
|
||||
justify-content: flex-end;
|
||||
align-self: flex-end;
|
||||
width: 100%;
|
||||
margin-top: $space-base;
|
||||
|
||||
> .action-buttons-group {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
> button {
|
||||
margin-left: 1em;
|
||||
min-width: fit-content;
|
||||
}
|
||||
> .ds-form-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
> .buttons-footer-helper {
|
||||
margin-right: 16px;
|
||||
// important needed because of component inline style
|
||||
margin-bottom: 6px !important;
|
||||
> .ds-chip {
|
||||
align-self: flex-end;
|
||||
margin: $space-xx-small 0 $space-base;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
> .select-field {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
> .buttons-footer {
|
||||
justify-content: flex-end;
|
||||
align-self: flex-end;
|
||||
width: 100%;
|
||||
margin-top: $space-base;
|
||||
|
||||
> .action-buttons-group {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
> button {
|
||||
margin-left: 1em;
|
||||
min-width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
> .buttons-footer-helper {
|
||||
margin-right: 16px;
|
||||
// important needed because of component inline style
|
||||
margin-bottom: 6px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,7 +613,7 @@ export default {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 656px) {
|
||||
> .buttons-footer {
|
||||
> .os-card__content > .buttons-footer {
|
||||
flex-direction: column;
|
||||
margin-top: 5px;
|
||||
|
||||
@ -617,7 +626,7 @@ export default {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 280px) {
|
||||
> .buttons-footer {
|
||||
> .os-card__content > .buttons-footer {
|
||||
> .action-buttons-group {
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card class="delete-data">
|
||||
<os-card class="delete-data">
|
||||
<h2 class="title">
|
||||
<os-icon :icon="icons.warning" />
|
||||
{{ $t('settings.deleteUserAccount.name') }}
|
||||
@ -55,11 +55,11 @@
|
||||
</template>
|
||||
{{ $t('settings.deleteUserAccount.name') }}
|
||||
</os-button>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
import gql from 'graphql-tag'
|
||||
@ -67,7 +67,7 @@ import { currentUserCountQuery } from '~/graphql/User'
|
||||
|
||||
export default {
|
||||
name: 'DeleteData',
|
||||
components: { OsButton, OsIcon },
|
||||
components: { OsButton, OsCard, OsIcon },
|
||||
data() {
|
||||
return {
|
||||
deleteContributions: false,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { storiesOf } from '@storybook/vue'
|
||||
import { withA11y } from '@storybook/addon-a11y'
|
||||
import ContentViewer from '~/components/Editor/ContentViewer.vue'
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import helpers from '~/storybook/helpers'
|
||||
|
||||
helpers.init()
|
||||
@ -10,11 +11,11 @@ storiesOf('ContentViewer', module)
|
||||
.addDecorator((storyFn) => {
|
||||
const ctx = storyFn()
|
||||
return {
|
||||
components: { ctx },
|
||||
components: { ctx, OsCard },
|
||||
template: `
|
||||
<base-card style="width: 50%; min-width: 500px; margin: 0 auto;">
|
||||
<os-card style="width: 50%; min-width: 500px; margin: 0 auto;">
|
||||
<ctx />
|
||||
</base-card>
|
||||
</os-card>
|
||||
`,
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { storiesOf } from '@storybook/vue'
|
||||
import { withA11y } from '@storybook/addon-a11y'
|
||||
import HcEditor from '~/components/Editor/Editor.vue'
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import helpers from '~/storybook/helpers'
|
||||
import Vue from 'vue'
|
||||
|
||||
@ -37,11 +38,11 @@ storiesOf('Editor', module)
|
||||
.addDecorator((storyFn) => {
|
||||
const ctx = storyFn()
|
||||
return {
|
||||
components: { ctx },
|
||||
components: { ctx, OsCard },
|
||||
template: `
|
||||
<base-card style="width: 50%; min-width: 500px; margin: 0 auto;">
|
||||
<os-card style="width: 50%; min-width: 500px; margin: 0 auto;">
|
||||
<ctx />
|
||||
</base-card>
|
||||
</os-card>
|
||||
`,
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
// import Vuex from 'vuex'
|
||||
// import locales from '~/locales'
|
||||
// import orderBy from 'lodash/orderBy'
|
||||
import LanguagesFilter from './LanguagesFilter'
|
||||
const localVue = global.localVue
|
||||
|
||||
// let wrapper, englishButton, spanishButton
|
||||
|
||||
// const languages = orderBy(locales, 'name')
|
||||
|
||||
describe('mount', () => {
|
||||
let wrapper
|
||||
const Wrapper = () => {
|
||||
return mount(LanguagesFilter, { localVue })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders button DIV', () => {
|
||||
expect(wrapper.find('div').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
// describe('LanguagesFilter.vue', () => {
|
||||
// const mutations = {
|
||||
// 'posts/TOGGLE_LANGUAGE': jest.fn(),
|
||||
// 'posts/RESET_LANGUAGES': jest.fn(),
|
||||
// }
|
||||
// const getters = {
|
||||
// 'posts/filteredLanguageCodes': jest.fn(() => []),
|
||||
// }
|
||||
|
||||
// const mocks = {
|
||||
// $t: jest.fn((string) => string),
|
||||
// }
|
||||
|
||||
// const Wrapper = () => {
|
||||
// const store = new Vuex.Store({ mutations, getters })
|
||||
// return mount(LanguagesFilter, { mocks, localVue, store })
|
||||
// }
|
||||
|
||||
// beforeEach(() => {
|
||||
// wrapper = Wrapper()
|
||||
// })
|
||||
|
||||
// describe('mount', () => {
|
||||
// it('starts with all categories button active', () => {
|
||||
// const allLanguagesButton = wrapper.find('.languages-filter .sidebar button')
|
||||
// expect(allLanguagesButton.attributes().class).toContain('--filled')
|
||||
// })
|
||||
|
||||
// it('sets language button attribute `filled` when corresponding language is filtered', () => {
|
||||
// getters['posts/filteredLanguageCodes'] = jest.fn(() => ['es'])
|
||||
// const wrapper = Wrapper()
|
||||
// spanishButton = wrapper
|
||||
// .findAll('.languages-filter .item button')
|
||||
// .at(languages.findIndex((l) => l.code === 'es'))
|
||||
// expect(spanishButton.attributes().class).toContain('--filled')
|
||||
// })
|
||||
|
||||
// describe('click on an "language-button" button', () => {
|
||||
// it('calls TOGGLE_LANGUAGE when clicked', () => {
|
||||
// const wrapper = Wrapper()
|
||||
// englishButton = wrapper
|
||||
// .findAll('.languages-filter .item button')
|
||||
// .at(languages.findIndex((l) => l.code === 'en'))
|
||||
// englishButton.trigger('click')
|
||||
// expect(mutations['posts/TOGGLE_LANGUAGE']).toHaveBeenCalledWith({}, 'en')
|
||||
// })
|
||||
// })
|
||||
|
||||
// describe('clears filter', () => {
|
||||
// it('when all button is clicked', async () => {
|
||||
// getters['posts/filteredLanguageCodes'] = jest.fn(() => ['en'])
|
||||
// wrapper = await Wrapper()
|
||||
// const allLanguagesButton = wrapper.find('.languages-filter .sidebar button')
|
||||
// allLanguagesButton.trigger('click')
|
||||
// expect(mutations['posts/RESET_LANGUAGES']).toHaveBeenCalledTimes(1)
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- <filter-menu-section :title="$t('filter-menu.languages')" class="languages-filter">
|
||||
<template>
|
||||
<labeled-button
|
||||
class="filter-languages"
|
||||
:filled="!filteredLanguageCodes.length"
|
||||
:label="$t('filter-menu.all')"
|
||||
icon="check"
|
||||
@click="resetLanguages"
|
||||
/>
|
||||
</template>
|
||||
<template #filter-list>
|
||||
<li v-for="language in locales" :key="language.code" class="item">
|
||||
<base-button
|
||||
:filled="filteredLanguageCodes.includes(language.code)"
|
||||
circle
|
||||
@click="toggleLanguage(language.code)"
|
||||
>
|
||||
{{ language.code.toUpperCase() }}
|
||||
</base-button>
|
||||
</li>
|
||||
</template>
|
||||
</filter-menu-section> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import { mapGetters, mapMutations } from 'vuex'
|
||||
// import orderBy from 'lodash/orderBy'
|
||||
// import locales from '~/locales'
|
||||
// import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
|
||||
// import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
|
||||
|
||||
// export default {
|
||||
// components: {
|
||||
// FilterMenuSection,
|
||||
// LabeledButton,
|
||||
// },
|
||||
// computed: {
|
||||
// ...mapGetters({
|
||||
// filteredLanguageCodes: 'posts/filteredLanguageCodes',
|
||||
// }),
|
||||
// },
|
||||
// methods: {
|
||||
// ...mapMutations({
|
||||
// resetLanguages: 'posts/RESET_LANGUAGES',
|
||||
// toggleLanguage: 'posts/TOGGLE_LANGUAGE',
|
||||
// }),
|
||||
// },
|
||||
// data() {
|
||||
// return {
|
||||
// locales: orderBy(locales, 'name'),
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
</script>
|
||||
@ -3,7 +3,7 @@
|
||||
class="group-teaser"
|
||||
:to="{ name: 'groups-id-slug', params: { id: group.id, slug: group.slug } }"
|
||||
>
|
||||
<base-card
|
||||
<os-card
|
||||
:class="{
|
||||
'disabled-content': group.disabled,
|
||||
}"
|
||||
@ -74,12 +74,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsIcon } from '@ocelot-social/ui'
|
||||
import { OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import Category from '~/components/Category'
|
||||
import GroupContentMenu from '~/components/ContentMenu/GroupContentMenu'
|
||||
@ -91,6 +91,7 @@ export default {
|
||||
components: {
|
||||
Category,
|
||||
GroupContentMenu,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
},
|
||||
props: {
|
||||
@ -130,7 +131,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.group-teaser > .base-card {
|
||||
.group-teaser > .os-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
@ -28,8 +28,7 @@ describe('HashtagsFilter.vue', () => {
|
||||
})
|
||||
|
||||
it('renders a card', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
|
||||
describe('click clear search button', () => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card class="hashtags-filter">
|
||||
<os-card class="hashtags-filter">
|
||||
<h2>{{ $t('hashtags-filter.hashtag-search', { hashtag }) }}</h2>
|
||||
<os-button
|
||||
data-test="clear-search-button"
|
||||
@ -14,15 +14,15 @@
|
||||
<os-icon :icon="icons.close" />
|
||||
</template>
|
||||
</os-button>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
|
||||
export default {
|
||||
components: { OsButton, OsIcon },
|
||||
components: { OsButton, OsCard, OsIcon },
|
||||
props: {
|
||||
hashtag: {
|
||||
type: String,
|
||||
@ -41,10 +41,10 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.hashtags-filter.base-card {
|
||||
.hashtags-filter.os-card {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: $space-x-small $space-base;
|
||||
padding: $space-x-small $space-base !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,58 +4,60 @@
|
||||
<p>{{ $t('quotes.african.quote') }}</p>
|
||||
<b>- {{ $t('quotes.african.author') }}</b>
|
||||
</blockquote>
|
||||
<base-card>
|
||||
<template #imageColumn>
|
||||
<os-card class="--columns">
|
||||
<aside class="image-column" :aria-label="$t('login.moreInfo', metadata)">
|
||||
<page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)">
|
||||
<logo logoType="welcome" />
|
||||
</page-params-link>
|
||||
</template>
|
||||
<h2 class="title">{{ $t('login.login') }}</h2>
|
||||
<form :disabled="pending" @submit.prevent="onSubmit">
|
||||
<ds-input
|
||||
v-model="form.email"
|
||||
:disabled="pending"
|
||||
:placeholder="$t('login.email')"
|
||||
type="email"
|
||||
name="email"
|
||||
icon="envelope"
|
||||
/>
|
||||
<div class="password-wrapper">
|
||||
</aside>
|
||||
<section class="content-column">
|
||||
<h2 class="title">{{ $t('login.login') }}</h2>
|
||||
<form :disabled="pending" @submit.prevent="onSubmit">
|
||||
<ds-input
|
||||
v-model="form.password"
|
||||
v-model="form.email"
|
||||
:disabled="pending"
|
||||
:placeholder="$t('login.password')"
|
||||
icon="lock"
|
||||
name="password"
|
||||
class="password-field"
|
||||
ref="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
:placeholder="$t('login.email')"
|
||||
type="email"
|
||||
name="email"
|
||||
icon="envelope"
|
||||
/>
|
||||
<show-password @show-password="toggleShowPassword" :icon="passwordIcon" />
|
||||
</div>
|
||||
<nuxt-link to="/password-reset/request">
|
||||
{{ $t('login.forgotPassword') }}
|
||||
</nuxt-link>
|
||||
<os-button
|
||||
:loading="pending"
|
||||
variant="primary"
|
||||
appearance="filled"
|
||||
full-width
|
||||
name="submit"
|
||||
type="submit"
|
||||
>
|
||||
<template #icon><os-icon :icon="icons.signIn" /></template>
|
||||
{{ $t('login.login') }}
|
||||
</os-button>
|
||||
<p>
|
||||
{{ $t('login.no-account') }}
|
||||
<nuxt-link to="/registration">{{ $t('login.register') }}</nuxt-link>
|
||||
</p>
|
||||
</form>
|
||||
<template #topMenu>
|
||||
<div class="password-wrapper">
|
||||
<ds-input
|
||||
v-model="form.password"
|
||||
:disabled="pending"
|
||||
:placeholder="$t('login.password')"
|
||||
icon="lock"
|
||||
name="password"
|
||||
class="password-field"
|
||||
ref="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
/>
|
||||
<show-password @show-password="toggleShowPassword" :icon="passwordIcon" />
|
||||
</div>
|
||||
<nuxt-link to="/password-reset/request">
|
||||
{{ $t('login.forgotPassword') }}
|
||||
</nuxt-link>
|
||||
<os-button
|
||||
:loading="pending"
|
||||
variant="primary"
|
||||
appearance="filled"
|
||||
full-width
|
||||
name="submit"
|
||||
type="submit"
|
||||
>
|
||||
<template #icon><os-icon :icon="icons.signIn" /></template>
|
||||
{{ $t('login.login') }}
|
||||
</os-button>
|
||||
<p>
|
||||
{{ $t('login.no-account') }}
|
||||
<nuxt-link to="/registration">{{ $t('login.register') }}</nuxt-link>
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
<aside class="top-menu" :aria-label="$t('localeSwitch.tooltip')">
|
||||
<locale-switch offset="5" />
|
||||
</template>
|
||||
</base-card>
|
||||
</aside>
|
||||
</os-card>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@ -66,7 +68,7 @@ import PageParamsLink from '~/components/_new/features/PageParamsLink/PageParams
|
||||
import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
|
||||
import Logo from '~/components/Logo/Logo'
|
||||
import ShowPassword from '../ShowPassword/ShowPassword.vue'
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
|
||||
@ -75,6 +77,7 @@ export default {
|
||||
LocaleSwitch,
|
||||
Logo,
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
PageParamsLink,
|
||||
ShowPassword,
|
||||
@ -135,7 +138,7 @@ export default {
|
||||
toggleShowPassword() {
|
||||
this.showPassword = !this.showPassword
|
||||
this.$nextTick(() => {
|
||||
this.$refs.password.$el.children[1].children[1].focus()
|
||||
this.$refs.password.$el.querySelector('input').focus()
|
||||
this.$emit('focus')
|
||||
})
|
||||
},
|
||||
|
||||
@ -18,74 +18,66 @@
|
||||
<ds-grid-item>
|
||||
<ds-flex class="user-section">
|
||||
<ds-flex-item>
|
||||
<base-card :wide-content="true">
|
||||
<client-only>
|
||||
<user-teaser
|
||||
:user="
|
||||
isGroup(notification.from)
|
||||
? notification.relatedUser
|
||||
: notification.from.author
|
||||
"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
:date-time="notification.from.createdAt"
|
||||
:injected-text="$t(`notifications.reason.${notification.reason}`)"
|
||||
:injected-date="true"
|
||||
:show-popover="showPopover"
|
||||
/>
|
||||
</client-only>
|
||||
</base-card>
|
||||
<user-teaser
|
||||
:user="
|
||||
isGroup(notification.from) ? notification.relatedUser : notification.from.author
|
||||
"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
:date-time="notification.from.createdAt"
|
||||
:injected-text="$t(`notifications.reason.${notification.reason}`)"
|
||||
:injected-date="true"
|
||||
:show-popover="showPopover"
|
||||
/>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</ds-grid-item>
|
||||
<ds-grid-item>
|
||||
<base-card :wide-content="true">
|
||||
<div class="notification-container">
|
||||
<!-- Icon with responsive sizing -->
|
||||
<div class="notification-icon">
|
||||
<os-icon
|
||||
v-if="notification.from.post"
|
||||
:icon="icons.comment"
|
||||
v-tooltip="{ content: $t('notifications.comment'), placement: 'right' }"
|
||||
/>
|
||||
<os-icon
|
||||
v-else
|
||||
:icon="icons.bookmark"
|
||||
v-tooltip="{ content: $t('notifications.post'), placement: 'right' }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Content section with title and description -->
|
||||
<div class="notification-content">
|
||||
<nuxt-link
|
||||
class="notification-mention-post"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
:to="{
|
||||
name: isGroup(notification.from) ? 'groups-id-slug' : 'post-id-slug',
|
||||
params: params(notification.from),
|
||||
hash: hashParam(notification.from),
|
||||
}"
|
||||
@click.native.prevent="handleNotificationClick(notification)"
|
||||
>
|
||||
<b>
|
||||
{{
|
||||
notification.from.title ||
|
||||
notification.from.groupName ||
|
||||
notification.from.post.title | truncate(50)
|
||||
}}
|
||||
</b>
|
||||
</nuxt-link>
|
||||
<p
|
||||
class="notification-description"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
>
|
||||
{{
|
||||
notification.from.contentExcerpt ||
|
||||
notification.from.descriptionExcerpt | removeHtml
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="notification-container">
|
||||
<!-- Icon with responsive sizing -->
|
||||
<div class="notification-icon">
|
||||
<os-icon
|
||||
v-if="notification.from.post"
|
||||
:icon="icons.comment"
|
||||
v-tooltip="{ content: $t('notifications.comment'), placement: 'right' }"
|
||||
/>
|
||||
<os-icon
|
||||
v-else
|
||||
:icon="icons.bookmark"
|
||||
v-tooltip="{ content: $t('notifications.post'), placement: 'right' }"
|
||||
/>
|
||||
</div>
|
||||
</base-card>
|
||||
|
||||
<!-- Content section with title and description -->
|
||||
<div class="notification-content">
|
||||
<nuxt-link
|
||||
class="notification-mention-post"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
:to="{
|
||||
name: isGroup(notification.from) ? 'groups-id-slug' : 'post-id-slug',
|
||||
params: params(notification.from),
|
||||
hash: hashParam(notification.from),
|
||||
}"
|
||||
@click.native.prevent="handleNotificationClick(notification)"
|
||||
>
|
||||
<b>
|
||||
{{
|
||||
notification.from.title ||
|
||||
notification.from.groupName ||
|
||||
(notification.from.post && notification.from.post.title) | truncate(50)
|
||||
}}
|
||||
</b>
|
||||
</nuxt-link>
|
||||
<p
|
||||
class="notification-description"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
>
|
||||
{{
|
||||
notification.from.contentExcerpt ||
|
||||
notification.from.descriptionExcerpt | removeHtml
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ds-grid-item>
|
||||
</ds-grid>
|
||||
</ds-grid-item>
|
||||
@ -98,7 +90,6 @@ import { OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import UserTeaser from '~/components/UserTeaser/UserTeaser'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
import BaseCard from '../_new/generic/BaseCard/BaseCard.vue'
|
||||
import mobile from '~/mixins/mobile'
|
||||
|
||||
const maxMobileWidth = 768 // at this point the table breaks down
|
||||
@ -109,7 +100,6 @@ export default {
|
||||
OsIcon,
|
||||
UserTeaser,
|
||||
HcEmpty,
|
||||
BaseCard,
|
||||
},
|
||||
props: {
|
||||
notifications: { type: Array, default: () => [] },
|
||||
@ -181,11 +171,6 @@ export default {
|
||||
.notification-grid .content-section {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.notification-grid .base-card {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
padding: 16px 4px;
|
||||
}
|
||||
/* dirty fix to override broken styleguide inline-styles */
|
||||
.notification-grid .ds-grid {
|
||||
grid-template-columns: 5fr 6fr !important;
|
||||
@ -201,9 +186,9 @@ export default {
|
||||
&:nth-child(odd) {
|
||||
background-color: $color-neutral-90;
|
||||
}
|
||||
.base-card {
|
||||
|
||||
> .ds-grid > div {
|
||||
padding: 8px 0;
|
||||
background-color: unset !important;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
class="post-teaser"
|
||||
:to="{ name: 'post-id-slug', params: { id: post.id, slug: post.slug } }"
|
||||
>
|
||||
<base-card
|
||||
<os-card
|
||||
:lang="post.language"
|
||||
:class="{
|
||||
'disabled-content': post.disabled,
|
||||
@ -138,12 +138,12 @@
|
||||
</span>
|
||||
</div>
|
||||
</client-only>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsIcon } from '@ocelot-social/ui'
|
||||
import { OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import Category from '~/components/Category'
|
||||
import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
||||
@ -165,6 +165,7 @@ export default {
|
||||
components: {
|
||||
Category,
|
||||
ContentMenu,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
CounterIcon,
|
||||
DateTimeRange,
|
||||
@ -197,7 +198,7 @@ export default {
|
||||
if (!image) return
|
||||
const width = this.$el.offsetWidth
|
||||
const height = Math.min(width / image.aspectRatio, 2000)
|
||||
const imageElement = this.$el.querySelector('.hero-image')
|
||||
const imageElement = this.$el.querySelector('.os-card__hero-image')
|
||||
if (imageElement) {
|
||||
imageElement.style.height = `${height}px`
|
||||
}
|
||||
@ -301,40 +302,46 @@ export default {
|
||||
position: absolute;
|
||||
// 14px (~height of ribbon element) + 24px(=margin of hero image)
|
||||
top: -38px;
|
||||
// 7px+24px(=padding of parent)
|
||||
right: -31px;
|
||||
// 7px+24px(=padding of parent) - 1px adjustment
|
||||
right: -29px;
|
||||
}
|
||||
> .post-ribbon {
|
||||
position: absolute;
|
||||
// 14px (~height of ribbon element) + 24px(=margin of hero image)
|
||||
top: -24px;
|
||||
// 7px(=offset)+24px(=margin of parent)
|
||||
right: -31px;
|
||||
// 7px(=offset)+24px(=margin of parent) - 2px adjustment
|
||||
right: -29px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-teaser > .base-card {
|
||||
.post-teaser > .os-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: visible;
|
||||
height: 100%;
|
||||
padding-bottom: $space-x-small;
|
||||
|
||||
> .hero-image {
|
||||
> .os-card__hero-image {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
&.--blur-image > .hero-image > .image {
|
||||
&.--blur-image > .os-card__hero-image .image {
|
||||
filter: blur($blur-radius);
|
||||
}
|
||||
|
||||
> .content {
|
||||
> .os-card__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
|
||||
> .footer {
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@ -363,7 +370,8 @@ export default {
|
||||
.user-teaser {
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
> .date-row {
|
||||
|
||||
.date-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: $space-small;
|
||||
|
||||
@ -3,45 +3,46 @@
|
||||
<div v-if="registrationType !== 'no-public-registration'" class="back-link" left>
|
||||
<nuxt-link :to="loginLink">{{ $t('site.back-to-login') }}</nuxt-link>
|
||||
</div>
|
||||
<base-card>
|
||||
<template #imageColumn>
|
||||
<os-card class="--columns">
|
||||
<aside class="image-column" :aria-label="$t('login.moreInfo', metadata)">
|
||||
<page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)">
|
||||
<logo logoType="signup" />
|
||||
</page-params-link>
|
||||
</template>
|
||||
</aside>
|
||||
<section class="content-column">
|
||||
<component-slider :sliderData="sliderData">
|
||||
<template #no-public-registration>
|
||||
<registration-slide-no-public :sliderData="sliderData" />
|
||||
</template>
|
||||
|
||||
<component-slider :sliderData="sliderData">
|
||||
<template #no-public-registration>
|
||||
<registration-slide-no-public :sliderData="sliderData" />
|
||||
</template>
|
||||
<template #enter-invite>
|
||||
<registration-slide-invite :sliderData="sliderData" />
|
||||
</template>
|
||||
|
||||
<template #enter-invite>
|
||||
<registration-slide-invite :sliderData="sliderData" />
|
||||
</template>
|
||||
<template #enter-email>
|
||||
<registration-slide-email :sliderData="sliderData" :invitation="false" />
|
||||
</template>
|
||||
|
||||
<template #enter-email>
|
||||
<registration-slide-email :sliderData="sliderData" :invitation="false" />
|
||||
</template>
|
||||
<template #enter-nonce>
|
||||
<registration-slide-nonce :sliderData="sliderData" />
|
||||
</template>
|
||||
|
||||
<template #enter-nonce>
|
||||
<registration-slide-nonce :sliderData="sliderData" />
|
||||
</template>
|
||||
|
||||
<template #create-user-account>
|
||||
<registration-slide-create :sliderData="sliderData" />
|
||||
</template>
|
||||
</component-slider>
|
||||
|
||||
<template #topMenu>
|
||||
<template #create-user-account>
|
||||
<registration-slide-create :sliderData="sliderData" />
|
||||
</template>
|
||||
</component-slider>
|
||||
</section>
|
||||
<aside class="top-menu" :aria-label="$t('localeSwitch.tooltip')">
|
||||
<locale-switch offset="5" />
|
||||
</template>
|
||||
</base-card>
|
||||
</aside>
|
||||
</os-card>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import links from '~/constants/links.js'
|
||||
import metadata from '~/constants/metadata.js'
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import ComponentSlider from '~/components/ComponentSlider/ComponentSlider'
|
||||
import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
|
||||
import Logo from '~/components/Logo/Logo'
|
||||
@ -58,6 +59,7 @@ export default {
|
||||
ComponentSlider,
|
||||
LocaleSwitch,
|
||||
Logo,
|
||||
OsCard,
|
||||
PageParamsLink,
|
||||
RegistrationSlideCreate,
|
||||
RegistrationSlideEmail,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<ds-space v-if="user.socialMedia && user.socialMedia.length" margin="large">
|
||||
<base-card class="social-media-bc">
|
||||
<os-card class="social-media-bc">
|
||||
<ds-space margin="x-small">
|
||||
<ds-text tag="h5" color="soft" data-test="social-media-list-headline">
|
||||
{{ $t('profile.socialMedia') }} {{ userName | truncate(15) }}?
|
||||
@ -14,16 +14,19 @@
|
||||
</ds-space>
|
||||
</template>
|
||||
</ds-space>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-space>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
|
||||
export default {
|
||||
name: 'social-media',
|
||||
components: { OsCard },
|
||||
props: {
|
||||
userName: {},
|
||||
user: {},
|
||||
userName: { type: String, required: true },
|
||||
user: { type: Object, required: true },
|
||||
},
|
||||
methods: {
|
||||
socialMediaLinks() {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
@vdropzone-file-added="fileAdded"
|
||||
>
|
||||
<os-spinner v-if="isLoadingImage" size="lg" />
|
||||
<os-icon v-else-if="!hasImage" :icon="icons.image" />
|
||||
<os-icon v-else-if="!hasImage" size="lg" :icon="icons.image" />
|
||||
<div v-if="!hasImage" class="supported-formats">
|
||||
{{ $t('contribution.teaserImage.supportedFormats') }}
|
||||
</div>
|
||||
@ -113,7 +113,9 @@ export default {
|
||||
const supportedFormats = ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
|
||||
if (supportedFormats.indexOf(file.type) < 0) {
|
||||
this.onUnSupportedFormat(this.$t('contribution.teaserImage.errors.unSupported-file-format'))
|
||||
this.$nextTick((this.isLoadingImage = false))
|
||||
this.$nextTick(() => {
|
||||
this.isLoadingImage = false
|
||||
})
|
||||
return null
|
||||
}
|
||||
const imageURL = URL.createObjectURL(file)
|
||||
@ -126,7 +128,9 @@ export default {
|
||||
this.saveImage(aspectRatio, file, file.type)
|
||||
this.file = file
|
||||
if (this.file.type === 'image/jpeg') this.imageCanBeCropped = true
|
||||
this.$nextTick((this.isLoadingImage = false))
|
||||
this.$nextTick(() => {
|
||||
this.isLoadingImage = false
|
||||
})
|
||||
},
|
||||
initCropper() {
|
||||
this.showCropper = true
|
||||
@ -138,7 +142,9 @@ export default {
|
||||
this.isLoadingImage = true
|
||||
const onCropComplete = (aspectRatio, imageFile, imageType) => {
|
||||
this.saveImage(aspectRatio, imageFile, imageType)
|
||||
this.$nextTick((this.isLoadingImage = false))
|
||||
this.$nextTick(() => {
|
||||
this.isLoadingImage = false
|
||||
})
|
||||
this.closeCropper()
|
||||
}
|
||||
if (this.file.type === 'image/jpeg') {
|
||||
|
||||
@ -10,24 +10,26 @@
|
||||
<br />
|
||||
<div v-html="$t(pageParams.internalPage.htmlIdent)" />
|
||||
</div>
|
||||
<base-card v-else>
|
||||
<os-card v-else>
|
||||
<div v-html="$t(pageParams.internalPage.htmlIdent)" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-container>
|
||||
<div v-else-if="!pageParams.internalPage.hasBaseCard">
|
||||
<br />
|
||||
<div v-html="$t(pageParams.internalPage.htmlIdent)" />
|
||||
</div>
|
||||
<base-card v-else>
|
||||
<os-card v-else>
|
||||
<div v-html="$t(pageParams.internalPage.htmlIdent)" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import { PageParams } from '~/components/utils/PageParams.js'
|
||||
|
||||
export default {
|
||||
components: { OsCard },
|
||||
name: 'InternalPage',
|
||||
props: {
|
||||
pageParams: { type: Object, required: true },
|
||||
@ -49,8 +51,8 @@ export default {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
|
||||
.base-card {
|
||||
padding: 16px !important;
|
||||
.os-card {
|
||||
padding: $space-small !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,25 +62,25 @@
|
||||
<!-- users -->
|
||||
<template v-if="activeTab === 'User'">
|
||||
<ds-grid-item v-for="user in activeResources" :key="user.id" :row-span="2">
|
||||
<base-card :wideContent="true">
|
||||
<os-card>
|
||||
<user-teaser :user="user" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-grid-item>
|
||||
</template>
|
||||
<!-- groups -->
|
||||
<template v-if="activeTab === 'Group'">
|
||||
<ds-grid-item v-for="group in activeResources" :key="group.id" :row-span="2">
|
||||
<base-card :wideContent="true" class="group-teaser-card-wrapper">
|
||||
<os-card class="group-teaser-card-wrapper">
|
||||
<group-teaser :group="{ ...group, name: group.groupName }" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-grid-item>
|
||||
</template>
|
||||
<!-- hashtags -->
|
||||
<template v-if="activeTab === 'Hashtag'">
|
||||
<ds-grid-item v-for="hashtag in activeResources" :key="hashtag.id" :row-span="2">
|
||||
<base-card :wideContent="true">
|
||||
<os-card>
|
||||
<hc-hashtag :id="hashtag.id" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-grid-item>
|
||||
</template>
|
||||
|
||||
@ -115,6 +115,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import postListActions from '~/mixins/postListActions'
|
||||
import { searchPosts, searchUsers, searchGroups, searchHashtags } from '~/graphql/Search.js'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
@ -130,6 +131,7 @@ import HcHashtag from '~/components/Hashtag/Hashtag'
|
||||
export default {
|
||||
name: 'SearchResults',
|
||||
components: {
|
||||
OsCard,
|
||||
TabNavigation,
|
||||
HcEmpty,
|
||||
MasonryGrid,
|
||||
|
||||
@ -1,133 +0,0 @@
|
||||
<template>
|
||||
<article :class="classNames">
|
||||
<template v-if="$slots.imageColumn">
|
||||
<aside class="image-column">
|
||||
<slot name="imageColumn" />
|
||||
</aside>
|
||||
<section class="content-column">
|
||||
<slot />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<template v-else-if="$slots.heroImage">
|
||||
<section class="hero-image">
|
||||
<slot name="heroImage" />
|
||||
</section>
|
||||
<slot />
|
||||
</template>
|
||||
|
||||
<slot v-else />
|
||||
<aside v-if="$slots.topMenu" class="top-menu">
|
||||
<slot name="topMenu" />
|
||||
</aside>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
highlight: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
wideContent: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classNames() {
|
||||
let classNames = 'base-card'
|
||||
|
||||
if (this.$slots.imageColumn) classNames += ' --columns'
|
||||
if (this.highlight) classNames += ' --highlight'
|
||||
if (this.wideContent) classNames += ' --wide-content'
|
||||
|
||||
return classNames
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.base-card {
|
||||
position: relative;
|
||||
padding: $space-base;
|
||||
border-radius: $border-radius-x-large;
|
||||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
background-color: $color-neutral-100;
|
||||
box-shadow: $box-shadow-base;
|
||||
|
||||
&.--columns {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.--highlight {
|
||||
border: $border-size-base solid $color-ribbon-announcement;
|
||||
}
|
||||
|
||||
&.--wide-content {
|
||||
padding: $space-small;
|
||||
|
||||
> .hero-image {
|
||||
width: calc(100% + (2 * #{$space-small}));
|
||||
margin: -$space-small;
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
}
|
||||
|
||||
> .title,
|
||||
> .content-column > .title {
|
||||
font-size: $font-size-large;
|
||||
margin-bottom: $space-x-small;
|
||||
}
|
||||
|
||||
> .hero-image {
|
||||
width: calc(100% + (2 * #{$space-base}));
|
||||
max-height: $size-image-max-height;
|
||||
margin: -$space-base;
|
||||
margin-bottom: $space-base;
|
||||
overflow: hidden;
|
||||
|
||||
> .image {
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
> .image-column {
|
||||
flex-basis: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-right: $space-base;
|
||||
|
||||
.image {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
> .content-column {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
|
||||
> .top-menu {
|
||||
position: absolute;
|
||||
top: $space-small;
|
||||
left: $space-small;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 565px) {
|
||||
.base-card.--columns {
|
||||
flex-direction: column;
|
||||
|
||||
> .image-column {
|
||||
padding-right: 0;
|
||||
margin-bottom: $space-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<ds-grid-item class="tab-navigation" :row-span="tabs.length" column-span="fullWidth">
|
||||
<base-card class="ds-tab-nav">
|
||||
<os-card class="ds-tab-nav">
|
||||
<ul class="Tabs">
|
||||
<li
|
||||
v-for="tab in tabs"
|
||||
@ -24,15 +24,17 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-grid-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcCountTo from '~/components/CountTo.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
HcCountTo,
|
||||
},
|
||||
props: {
|
||||
@ -42,6 +44,7 @@ export default {
|
||||
},
|
||||
activeTab: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@ -93,8 +96,8 @@ export default {
|
||||
top: 53px;
|
||||
z-index: 2;
|
||||
}
|
||||
.ds-tab-nav.base-card {
|
||||
padding: 0;
|
||||
.ds-tab-nav.os-card {
|
||||
padding: 0 !important;
|
||||
|
||||
.ds-tab-nav-item {
|
||||
&.ds-tab-nav-item-active {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { faker } from '@faker-js/faker'
|
||||
import { storiesOf } from '@storybook/vue'
|
||||
import { withA11y } from '@storybook/addon-a11y'
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid'
|
||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem'
|
||||
@ -72,6 +73,7 @@ storiesOf('TabNavigator', module)
|
||||
PostTeaser,
|
||||
UserTeaser,
|
||||
HcHashtag,
|
||||
OsCard,
|
||||
},
|
||||
store: helpers.store,
|
||||
data: () => ({
|
||||
@ -160,17 +162,17 @@ storiesOf('TabNavigator', module)
|
||||
<!-- users -->
|
||||
<template v-if="activeTab === 'User'">
|
||||
<ds-grid-item v-for="user in activeResources" :key="user.id" :row-span="2">
|
||||
<base-card :wideContent="true">
|
||||
<os-card>
|
||||
<user-teaser :user="user" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-grid-item>
|
||||
</template>
|
||||
<!-- hashtags -->
|
||||
<template v-if="activeTab === 'Hashtag'">
|
||||
<ds-grid-item v-for="hashtag in activeResources" :key="hashtag.id" :row-span="2">
|
||||
<base-card :wideContent="true">
|
||||
<os-card>
|
||||
<hc-hashtag :id="hashtag.id" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-grid-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card class="profile-list">
|
||||
<os-card class="profile-list">
|
||||
<template v-if="profiles.length">
|
||||
<h5 class="title spacer-x-small">
|
||||
{{ title }}
|
||||
@ -60,11 +60,11 @@
|
||||
</os-button>
|
||||
</template>
|
||||
<p v-else-if="titleNobody" class="nobody-message">{{ titleNobody }}</p>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard } from '@ocelot-social/ui'
|
||||
import { escape } from 'xregexp/xregexp-all.js'
|
||||
// @ts-ignore
|
||||
import { RecycleScroller } from 'vue-virtual-scroller'
|
||||
@ -78,6 +78,7 @@ export default {
|
||||
name: 'ProfileList',
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
UserTeaser,
|
||||
RecycleScroller,
|
||||
},
|
||||
@ -172,7 +173,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.profile-list {
|
||||
.profile-list.os-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { storiesOf } from '@storybook/vue'
|
||||
import { withA11y } from '@storybook/addon-a11y'
|
||||
import { action } from '@storybook/addon-actions'
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import { post } from '~/components/PostTeaser/PostTeaser.story.js'
|
||||
import { user } from '~/components/UserTeaser/UserTeaser.story.js'
|
||||
import helpers from '~/storybook/helpers'
|
||||
@ -172,7 +173,7 @@ storiesOf('ReportList', module)
|
||||
.addDecorator(withA11y)
|
||||
.addDecorator(helpers.layout)
|
||||
.add('with reports', () => ({
|
||||
components: { ReportList, DropdownFilter, ReportsTable },
|
||||
components: { ReportList, DropdownFilter, ReportsTable, OsCard },
|
||||
store: helpers.store,
|
||||
data: () => ({
|
||||
filterOptions,
|
||||
@ -183,11 +184,11 @@ storiesOf('ReportList', module)
|
||||
openModal: action('openModal'),
|
||||
filter: action('filter'),
|
||||
},
|
||||
template: `<base-card>
|
||||
template: `<os-card>
|
||||
<div class="reports-header">
|
||||
<h3 class="title">Reports</h3>
|
||||
<dropdown-filter @filter="filter" :filterOptions="filterOptions" :selected="selected" />
|
||||
</div>
|
||||
<reports-table :reports="reports" @confirm="openModal" />
|
||||
</base-card>`,
|
||||
</os-card>`,
|
||||
}))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<div class="reports-header">
|
||||
<h3 class="title">{{ $t('moderation.reports.name') }}</h3>
|
||||
<client-only>
|
||||
@ -8,10 +8,11 @@
|
||||
</div>
|
||||
<reports-table :reports="reports" @confirm="openModal" />
|
||||
<pagination-buttons :hasNext="hasNext" :hasPrevious="hasPrevious" @back="back" @next="next" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapMutations } from 'vuex'
|
||||
import DropdownFilter from '~/components/DropdownFilter/DropdownFilter'
|
||||
@ -21,6 +22,7 @@ import PaginationButtons from '~/components/_new/generic/PaginationButtons/Pagin
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
DropdownFilter,
|
||||
ReportsTable,
|
||||
PaginationButtons,
|
||||
|
||||
@ -38,7 +38,6 @@ export default {
|
||||
styleResources,
|
||||
|
||||
plugins: [
|
||||
{ src: '~/plugins/base-components.js', ssr: true },
|
||||
{ src: `~/plugins/styleguide.js`, ssr: true },
|
||||
{ src: '~/plugins/i18n.js', ssr: true },
|
||||
{ src: '~/plugins/v-tooltip.js', ssr: false },
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<transition name="fade" appear>
|
||||
<ds-container width="medium">
|
||||
<base-card>
|
||||
<os-card>
|
||||
<ds-space>
|
||||
<locale-switch class="login-locale-switch" offset="5" />
|
||||
</ds-space>
|
||||
@ -38,12 +38,13 @@
|
||||
</ds-flex-item>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-container>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import emails from '~/constants/emails.js'
|
||||
// import links from '~/constants/links.js'
|
||||
import metadata from '~/constants/metadata.js'
|
||||
@ -53,6 +54,7 @@ import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
|
||||
export default {
|
||||
layout: 'blank',
|
||||
components: {
|
||||
OsCard,
|
||||
LocaleSwitch,
|
||||
// Logo,
|
||||
},
|
||||
|
||||
@ -109,7 +109,6 @@ export default {
|
||||
** Plugins to load before mounting the App
|
||||
*/
|
||||
plugins: [
|
||||
{ src: '~/plugins/base-components.js', ssr: true },
|
||||
{
|
||||
src: `~/plugins/styleguide.js`,
|
||||
ssr: true,
|
||||
|
||||
@ -19,13 +19,11 @@ exports[`_static mount renders 1`] = `
|
||||
<div
|
||||
class="ds-container ds-container-x-large"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<div />
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -26,7 +26,7 @@ describe('categories.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.categories.name') }}</h2>
|
||||
<ds-table :data="Category" :fields="fields" condensed>
|
||||
<template #icon="scope">
|
||||
<os-icon :icon="resolveIcon(scope.row.icon)" />
|
||||
</template>
|
||||
</ds-table>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsIcon } from '@ocelot-social/ui'
|
||||
import { OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { resolveIcon } from '~/utils/iconRegistry'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
components: { OsIcon },
|
||||
components: { OsCard, OsIcon },
|
||||
data() {
|
||||
return {
|
||||
Category: [],
|
||||
|
||||
@ -57,7 +57,7 @@ describe('donations.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
|
||||
describe('displays', () => {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.donations.name') }}</h2>
|
||||
<ds-form v-model="formData" @submit="submit">
|
||||
<ds-text class="show-donations-checkbox">
|
||||
@ -32,15 +32,15 @@
|
||||
{{ $t('actions.save') }}
|
||||
</os-button>
|
||||
</ds-form>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard } from '@ocelot-social/ui'
|
||||
import { DonationsQuery, UpdateDonations } from '~/graphql/Donations'
|
||||
|
||||
export default {
|
||||
components: { OsButton },
|
||||
components: { OsButton, OsCard },
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
|
||||
@ -26,7 +26,7 @@ describe('hashtags.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.hashtags.name') }}</h2>
|
||||
<ds-table :data="Tag" :fields="fields" condensed>
|
||||
<template #index="scope">{{ scope.index + 1 }}.</template>
|
||||
@ -9,13 +9,15 @@
|
||||
</nuxt-link>
|
||||
</template>
|
||||
</ds-table>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
components: { OsCard },
|
||||
data() {
|
||||
return {
|
||||
Tag: [],
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<template v-if="$apollo.loading">
|
||||
<div style="text-align: center; padding: 48px 0">
|
||||
<os-spinner size="xl" />
|
||||
@ -34,16 +34,17 @@
|
||||
</ds-text>
|
||||
</ds-space>
|
||||
</template>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsSpinner } from '@ocelot-social/ui'
|
||||
import { OsCard, OsSpinner } from '@ocelot-social/ui'
|
||||
import HcCountTo from '~/components/CountTo.vue'
|
||||
import { Statistics } from '~/graphql/admin/Statistics'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
OsSpinner,
|
||||
HcCountTo,
|
||||
},
|
||||
|
||||
@ -4,17 +4,19 @@
|
||||
<ds-heading size="h3">{{ $t('admin.invites.title') }}</ds-heading>
|
||||
<ds-text>{{ $t('admin.invites.description') }}</ds-text>
|
||||
</ds-space>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<signup :invitation="true" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import Signup from '~/components/Registration/Signup'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
Signup,
|
||||
},
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ describe('notifications.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.notifications.name') }}</h2>
|
||||
<hc-empty icon="tasks" message="Coming Soon…" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
HcEmpty,
|
||||
},
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ describe('organizations.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.organizations.name') }}</h2>
|
||||
<hc-empty icon="tasks" message="Coming Soon…" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
HcEmpty,
|
||||
},
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ describe('pages.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.pages.name') }}</h2>
|
||||
<hc-empty icon="tasks" message="Coming Soon…" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
HcEmpty,
|
||||
},
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ describe('settings.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.settings.name') }}</h2>
|
||||
<hc-empty icon="tasks" message="Coming Soon…" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
HcEmpty,
|
||||
},
|
||||
}
|
||||
|
||||
@ -33,8 +33,8 @@ exports[`.vue renders 1`] = `
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<div
|
||||
class="badge-section"
|
||||
@ -93,9 +93,7 @@ exports[`.vue renders 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -4,8 +4,8 @@ exports[`Users given badges are disabled renders 1`] = `
|
||||
<div
|
||||
class="admin-users"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -119,12 +119,10 @@ exports[`Users given badges are disabled renders 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<div
|
||||
class="ds-table-wrap"
|
||||
@ -452,9 +450,7 @@ exports[`Users given badges are disabled renders 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -462,8 +458,8 @@ exports[`Users given badges are enabled renders 1`] = `
|
||||
<div
|
||||
class="admin-users"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -577,12 +573,10 @@ exports[`Users given badges are enabled renders 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<div
|
||||
class="ds-table-wrap"
|
||||
@ -988,8 +982,6 @@ exports[`Users given badges are enabled renders 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</ds-heading>
|
||||
<ds-text>{{ $t('admin.badges.description') }}</ds-text>
|
||||
</ds-space>
|
||||
<base-card v-if="!isLoadingBadges">
|
||||
<os-card v-if="!isLoadingBadges">
|
||||
<badges-section
|
||||
:title="$t('admin.badges.verificationBadges')"
|
||||
:badges="verificationBadges"
|
||||
@ -19,11 +19,12 @@
|
||||
:badges="trophyBadges"
|
||||
@toggleBadge="toggleBadge"
|
||||
/>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import BadgesSection from '~/components/_new/features/Admin/Badges/BadgesSection.vue'
|
||||
import {
|
||||
queryBadges,
|
||||
@ -35,6 +36,7 @@ import { adminUserBadgesQuery } from '~/graphql/User'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
BadgesSection,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="admin-users">
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('admin.users.name') }}</h2>
|
||||
<ds-form v-model="form" @submit="submit">
|
||||
<ds-flex gutter="small">
|
||||
@ -25,8 +25,8 @@
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</ds-form>
|
||||
</base-card>
|
||||
<base-card v-if="User && User.length">
|
||||
</os-card>
|
||||
<os-card v-if="User && User.length">
|
||||
<ds-table :data="User" :fields="fields" condensed>
|
||||
<template #index="scope">{{ scope.row.index + 1 }}.</template>
|
||||
<template #name="scope">
|
||||
@ -89,15 +89,15 @@
|
||||
</template>
|
||||
</ds-table>
|
||||
<pagination-buttons :hasNext="hasNext" :hasPrevious="hasPrevious" @next="next" @back="back" />
|
||||
</base-card>
|
||||
<base-card v-else>
|
||||
</os-card>
|
||||
<os-card v-else>
|
||||
<ds-placeholder>{{ $t('admin.users.empty') }}</ds-placeholder>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { isEmail } from 'validator'
|
||||
@ -108,6 +108,7 @@ import { FetchAllRoles, updateUserRole } from '~/graphql/admin/Roles'
|
||||
export default {
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
PaginationButtons,
|
||||
},
|
||||
@ -241,7 +242,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.admin-users > .base-card:first-child {
|
||||
.admin-users > .os-card:first-child {
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
|
||||
|
||||
@ -18,8 +18,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -566,9 +566,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -584,8 +582,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -927,9 +925,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -940,8 +936,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -979,9 +975,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -1159,8 +1153,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -1465,9 +1459,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -1483,17 +1475,15 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<p
|
||||
class="nobody-message"
|
||||
>
|
||||
group.membersListTitleNotAllowedSeeingGroupMembers
|
||||
</p>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -1504,8 +1494,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -1543,9 +1533,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
@ -1688,8 +1676,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -2014,9 +2002,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -2032,17 +2018,15 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<p
|
||||
class="nobody-message"
|
||||
>
|
||||
group.membersListTitleNotAllowedSeeingGroupMembers
|
||||
</p>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -2053,8 +2037,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -2092,9 +2076,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
@ -2237,8 +2219,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -2696,9 +2678,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -2714,8 +2694,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -3057,9 +3037,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -3070,8 +3048,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -3109,9 +3087,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -3289,8 +3265,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -3762,9 +3738,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -3780,8 +3754,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -4123,9 +4097,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -4136,8 +4108,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -4180,9 +4152,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -4360,8 +4330,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -4629,9 +4599,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -4647,8 +4615,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -4990,9 +4958,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -5003,8 +4969,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -5047,9 +5013,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
@ -5192,8 +5156,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -5481,9 +5445,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -5499,8 +5461,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -5842,9 +5804,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -5855,8 +5815,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -5899,9 +5859,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
@ -6044,8 +6002,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -6428,9 +6386,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -6446,8 +6402,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -6789,9 +6745,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -6802,8 +6756,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -6846,9 +6800,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a curre
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -7026,8 +6978,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -7574,9 +7526,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -7592,8 +7542,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -7935,9 +7885,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -7948,8 +7896,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -8004,9 +7952,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -8196,8 +8142,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -8655,9 +8601,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -8673,8 +8617,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
</h3>
|
||||
|
||||
<article
|
||||
class="profile-list base-card"
|
||||
<div
|
||||
class="profile-list os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 profile-list"
|
||||
>
|
||||
<h5
|
||||
class="title spacer-x-small"
|
||||
@ -9016,9 +8960,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -9029,8 +8971,8 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
class="ds-space"
|
||||
style="margin-bottom: 32px;"
|
||||
>
|
||||
<article
|
||||
class="group-description base-card"
|
||||
<div
|
||||
class="group-description os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 group-description"
|
||||
>
|
||||
<div
|
||||
class="content hyphenate-text"
|
||||
@ -9085,9 +9027,7 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<ds-space />
|
||||
<ds-flex v-if="group" :width="{ base: '100%' }" gutter="base">
|
||||
<ds-flex-item :width="{ base: '100%', sm: 2, md: 2, lg: 1 }">
|
||||
<base-card
|
||||
<os-card
|
||||
:class="{ 'disabled-content': group.disabled }"
|
||||
style="position: relative; height: auto; overflow: visible"
|
||||
>
|
||||
@ -169,7 +169,7 @@
|
||||
</div>
|
||||
</ds-space>
|
||||
</template>
|
||||
</base-card>
|
||||
</os-card>
|
||||
<ds-space />
|
||||
<ds-heading tag="h3" soft style="text-align: center; margin-bottom: 10px">
|
||||
{{ $t('profile.network.title') }}
|
||||
@ -196,7 +196,7 @@
|
||||
<ds-flex-item :width="{ base: '100%', sm: 3, md: 5, lg: 3 }">
|
||||
<!-- Group description -->
|
||||
<ds-space>
|
||||
<base-card class="group-description">
|
||||
<os-card class="group-description">
|
||||
<!-- TODO: replace editor content with tiptap render view -->
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<div
|
||||
@ -214,7 +214,7 @@
|
||||
>
|
||||
{{ isDescriptionCollapsed ? $t('comment.show.more') : $t('comment.show.less') }}
|
||||
</os-button>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-space>
|
||||
<ds-space v-if="isGroupMemberNonePending" centered>
|
||||
<os-button
|
||||
@ -290,7 +290,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon, OsSpinner } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon, OsSpinner } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import uniqBy from 'lodash/uniqBy'
|
||||
import { profilePagePosts } from '~/graphql/PostQuery'
|
||||
@ -327,6 +327,7 @@ import GetCategories from '~/mixins/getCategoriesMixin.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
OsButton,
|
||||
OsIcon,
|
||||
OsSpinner,
|
||||
@ -673,17 +674,18 @@ export default {
|
||||
.chip {
|
||||
margin-bottom: $space-x-small;
|
||||
}
|
||||
.group-description > .base-card {
|
||||
.group-description.os-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding-bottom: $space-base !important;
|
||||
|
||||
> .content {
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
}
|
||||
.collaps-button {
|
||||
float: right;
|
||||
align-self: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
</ds-space>
|
||||
<ds-space margin="large" />
|
||||
<ds-container>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<ds-space margin="large">
|
||||
<ds-flex :width="{ base: '100%' }" gutter="base">
|
||||
<ds-flex-item :width="{ base: '100%', md: 5 }">
|
||||
@ -16,17 +16,19 @@
|
||||
<ds-flex-item :width="{ base: '100%', md: 1 }"> </ds-flex-item>
|
||||
</ds-flex>
|
||||
</ds-space>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import GroupForm from '~/components/Group/GroupForm'
|
||||
import { createGroupMutation } from '~/graphql/groups.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
GroupForm,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
exports[`invites.vue renders 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h3
|
||||
class="ds-heading ds-heading-h3"
|
||||
@ -207,9 +207,7 @@ exports[`invites.vue renders 1`] = `
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
<template>
|
||||
<div>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<ds-heading tag="h3">{{ $t('group.general') }}</ds-heading>
|
||||
<ds-space margin="large" />
|
||||
<group-form :group="group" :update="true" @updateGroup="updateGroup" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import GroupForm from '~/components/Group/GroupForm'
|
||||
import { updateGroupMutation } from '~/graphql/groups.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
GroupForm,
|
||||
},
|
||||
props: {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<ds-heading tag="h3">{{ $t('invite-codes.group-invite-links') }}</ds-heading>
|
||||
<ds-space margin="large" />
|
||||
<invitation-list
|
||||
@ -18,16 +18,18 @@
|
||||
})
|
||||
"
|
||||
/>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import InvitationList from '~/components/_new/features/Invitations/InvitationList.vue'
|
||||
import { generateGroupInviteCode, invalidateInviteCode } from '~/graphql/InviteCode'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
InvitationList,
|
||||
},
|
||||
props: {
|
||||
|
||||
@ -6,23 +6,25 @@
|
||||
@loadGroupMembers="loadGroupMembers"
|
||||
/>
|
||||
<ds-space margin-bottom="small" />
|
||||
<base-card>
|
||||
<os-card>
|
||||
<group-member
|
||||
:groupId="group.id"
|
||||
:groupMembers="groupMembers"
|
||||
@loadGroupMembers="loadGroupMembers"
|
||||
/>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import GroupMember from '~/components/Group/GroupMember'
|
||||
import AddGroupMember from '~/components/Group/AddGroupMember'
|
||||
import { groupMembersQuery } from '~/graphql/groups.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
GroupMember,
|
||||
AddGroupMember,
|
||||
},
|
||||
|
||||
@ -27,7 +27,7 @@ describe('moderation/index.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<ds-flex class="notifications-page-flex">
|
||||
<ds-flex-item :width="{ lg: '85%' }">
|
||||
<ds-heading tag="h3">{{ $t('notifications.title') }}</ds-heading>
|
||||
@ -38,11 +38,11 @@
|
||||
/>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard } from '@ocelot-social/ui'
|
||||
import NotificationsTable from '~/components/NotificationsTable/NotificationsTable'
|
||||
import DropdownFilter from '~/components/DropdownFilter/DropdownFilter'
|
||||
import PaginationButtons from '~/components/_new/generic/PaginationButtons/PaginationButtons'
|
||||
@ -50,6 +50,7 @@ import { notificationQuery, markAsReadMutation, markAllAsReadMutation } from '~/
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
OsButton,
|
||||
DropdownFilter,
|
||||
NotificationsTable,
|
||||
|
||||
@ -4,17 +4,19 @@
|
||||
<nuxt-link to="/login">{{ $t('site.back-to-login') }}</nuxt-link>
|
||||
</div>
|
||||
|
||||
<base-card>
|
||||
<template #imageColumn>
|
||||
<os-card class="--columns">
|
||||
<aside class="image-column" :aria-label="$t('login.moreInfo', metadata)">
|
||||
<page-params-link :pageParams="links.ORGANIZATION" :title="$t('login.moreInfo', metadata)">
|
||||
<logo logoType="passwordReset" />
|
||||
</page-params-link>
|
||||
</template>
|
||||
<nuxt-child />
|
||||
<template #topMenu>
|
||||
</aside>
|
||||
<section class="content-column">
|
||||
<nuxt-child />
|
||||
</section>
|
||||
<aside class="top-menu" :aria-label="$t('localeSwitch.tooltip')">
|
||||
<locale-switch offset="5" />
|
||||
</template>
|
||||
</base-card>
|
||||
</aside>
|
||||
</os-card>
|
||||
</ds-container>
|
||||
</template>
|
||||
|
||||
@ -22,6 +24,7 @@
|
||||
import links from '~/constants/links.js'
|
||||
import metadata from '~/constants/metadata.js'
|
||||
import loginConstants from '~/constants/loginBranded.js'
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
|
||||
import Logo from '~/components/Logo/Logo'
|
||||
import PageParamsLink from '~/components/_new/features/PageParamsLink/PageParamsLink.vue'
|
||||
@ -30,6 +33,7 @@ export default {
|
||||
components: {
|
||||
LocaleSwitch,
|
||||
Logo,
|
||||
OsCard,
|
||||
PageParamsLink,
|
||||
},
|
||||
layout: loginConstants.LAYOUT,
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<ds-space margin="large" />
|
||||
<ds-flex gutter="small">
|
||||
<ds-flex-item :width="{ base: '100%', sm: 2, md: 2, lg: 1 }">
|
||||
<base-card
|
||||
<os-card
|
||||
v-if="post && ready"
|
||||
:lang="post.language"
|
||||
:class="{
|
||||
@ -170,7 +170,7 @@
|
||||
</hc-empty>
|
||||
</ds-placeholder>
|
||||
</ds-section>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item :width="{ base: '200px' }">
|
||||
<ds-menu :routes="routes" class="post-side-navigation" />
|
||||
@ -181,7 +181,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import ContentViewer from '~/components/Editor/ContentViewer'
|
||||
import CommentForm from '~/components/CommentForm/CommentForm'
|
||||
@ -218,6 +218,7 @@ export default {
|
||||
mode: 'out-in',
|
||||
},
|
||||
components: {
|
||||
OsCard,
|
||||
OsButton,
|
||||
OsIcon,
|
||||
CommentForm,
|
||||
@ -426,14 +427,14 @@ export default {
|
||||
z-index: 2;
|
||||
}
|
||||
.post-page {
|
||||
> .hero-image {
|
||||
> .os-card__hero-image {
|
||||
position: relative;
|
||||
/* The padding top makes sure the correct height is set (according to the
|
||||
hero image aspect ratio) before the hero image loads so
|
||||
the autoscroll works correctly when following a comment link.
|
||||
*/
|
||||
|
||||
padding-top: calc(var(--hero-image-aspect-ratio) * (100% + 48px));
|
||||
padding-top: calc(var(--hero-image-aspect-ratio) * 100%);
|
||||
/* Letting the image fill the container, since the container
|
||||
is the one determining height
|
||||
*/
|
||||
@ -446,13 +447,13 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
> .menu {
|
||||
.menu {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.--blur-image > .hero-image > .image {
|
||||
&.--blur-image > .os-card__hero-image > .image {
|
||||
filter: blur($blur-radius);
|
||||
}
|
||||
|
||||
|
||||
@ -16,8 +16,8 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -435,9 +435,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -483,8 +481,8 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
class="tab-navigation"
|
||||
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
|
||||
>
|
||||
<article
|
||||
class="ds-tab-nav base-card"
|
||||
<div
|
||||
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
|
||||
>
|
||||
<ul
|
||||
class="Tabs"
|
||||
@ -628,9 +626,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
@ -765,8 +761,8 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -1221,9 +1217,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -1269,8 +1263,8 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
class="tab-navigation"
|
||||
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
|
||||
>
|
||||
<article
|
||||
class="ds-tab-nav base-card"
|
||||
<div
|
||||
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
|
||||
>
|
||||
<ul
|
||||
class="Tabs"
|
||||
@ -1414,9 +1408,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
@ -1551,8 +1543,8 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -1830,9 +1822,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -1878,8 +1868,8 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
class="tab-navigation"
|
||||
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
|
||||
>
|
||||
<article
|
||||
class="ds-tab-nav base-card"
|
||||
<div
|
||||
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
|
||||
>
|
||||
<ul
|
||||
class="Tabs"
|
||||
@ -2023,9 +2013,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -2198,8 +2186,8 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
class="ds-flex-item"
|
||||
style="flex-basis: 100%; width: 100%; padding-left: 12px; padding-right: 12px; margin-bottom: 24px;"
|
||||
>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
style="position: relative; height: auto; overflow: visible;"
|
||||
>
|
||||
<div
|
||||
@ -2519,9 +2507,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
@ -2567,8 +2553,8 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
class="tab-navigation"
|
||||
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
|
||||
>
|
||||
<article
|
||||
class="ds-tab-nav base-card"
|
||||
<div
|
||||
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
|
||||
>
|
||||
<ul
|
||||
class="Tabs"
|
||||
@ -2712,9 +2698,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<ds-space />
|
||||
<ds-flex v-if="user" :width="{ base: '100%' }" gutter="base">
|
||||
<ds-flex-item :width="{ base: '100%', sm: 2, md: 2, lg: 1 }">
|
||||
<base-card
|
||||
<os-card
|
||||
:class="{ 'disabled-content': user.disabled }"
|
||||
style="position: relative; height: auto; overflow: visible"
|
||||
>
|
||||
@ -117,7 +117,7 @@
|
||||
</ds-text>
|
||||
</ds-space>
|
||||
</template>
|
||||
</base-card>
|
||||
</os-card>
|
||||
<ds-space />
|
||||
<ds-heading tag="h3" soft style="text-align: center; margin-bottom: 10px">
|
||||
{{ $t('profile.network.title') }}
|
||||
@ -212,7 +212,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon, OsSpinner } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon, OsSpinner } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import uniqBy from 'lodash/uniqBy'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
@ -247,6 +247,7 @@ const tabToFilterMapping = ({ tab, id }) => {
|
||||
|
||||
export default {
|
||||
components: {
|
||||
OsCard,
|
||||
OsButton,
|
||||
OsIcon,
|
||||
OsSpinner,
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
exports[`badge settings with badges more badges available selecting an empty slot shows list with available badges 1`] = `
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -129,16 +129,14 @@ exports[`badge settings with badges more badges available selecting an empty slo
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`badge settings with badges no more badges available selecting an empty slot shows no more badges available message 1`] = `
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -211,16 +209,14 @@ exports[`badge settings with badges no more badges available selecting an empty
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`badge settings with badges renders 1`] = `
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -295,92 +291,14 @@ exports[`badge settings with badges renders 1`] = `
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`badge settings with badges selecting a used badge clicking remove badge button with successful server request removes the badge 1`] = `
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
>
|
||||
settings.badges.name
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
settings.badges.description
|
||||
</p>
|
||||
|
||||
<div
|
||||
class="ds-space"
|
||||
>
|
||||
<div
|
||||
class="presenterContainer"
|
||||
>
|
||||
<div
|
||||
class="hc-badges"
|
||||
style="transform: scale(2);"
|
||||
>
|
||||
<button
|
||||
class="hc-badge-container"
|
||||
>
|
||||
<img
|
||||
class="hc-badge"
|
||||
src="/api/verification/icon"
|
||||
title="Verification description"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="hc-badge-container selectable"
|
||||
>
|
||||
<img
|
||||
class="hc-badge"
|
||||
src="/api/path/to/some/icon"
|
||||
title="Some description"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="hc-badge-container selectable"
|
||||
>
|
||||
<img
|
||||
class="hc-badge"
|
||||
src="/api/path/to/empty/icon"
|
||||
title="Empty"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="hc-badge-container selectable"
|
||||
>
|
||||
<img
|
||||
class="hc-badge"
|
||||
src="/api/path/to/third/icon"
|
||||
title="Third description"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`badge settings without badges renders 1`] = `
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -422,8 +340,6 @@ exports[`badge settings without badges renders 1`] = `
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
exports[`notifications.vue mount renders 1`] = `
|
||||
<div>
|
||||
<article
|
||||
class="base-card"
|
||||
<div
|
||||
class="os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6"
|
||||
>
|
||||
<h2
|
||||
class="title"
|
||||
@ -206,8 +206,6 @@ exports[`notifications.vue mount renders 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('settings.badges.name') }}</h2>
|
||||
<p>{{ $t('settings.badges.description') }}</p>
|
||||
<ds-space centered margin-bottom="small" margin-top="base">
|
||||
@ -50,11 +50,11 @@
|
||||
/>
|
||||
</div>
|
||||
</ds-space>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard } from '@ocelot-social/ui'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { setTrophyBadgeSelected } from '~/graphql/User'
|
||||
import scrollToContent from './scroll-to-content.js'
|
||||
@ -62,7 +62,7 @@ import Badges from '../../components/Badges.vue'
|
||||
import BadgeSelection from '../../components/BadgeSelection.vue'
|
||||
|
||||
export default {
|
||||
components: { OsButton, BadgeSelection, Badges },
|
||||
components: { OsButton, OsCard, BadgeSelection, Badges },
|
||||
mixins: [scrollToContent],
|
||||
data() {
|
||||
return {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-space>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('settings.blocked-users.name') }}</h2>
|
||||
<ds-text>
|
||||
{{ $t('settings.blocked-users.explanation.intro') }}
|
||||
@ -17,9 +17,9 @@
|
||||
{{ $t('settings.blocked-users.explanation.notifications') }}
|
||||
</ds-list-item>
|
||||
</ds-list>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</ds-space>
|
||||
<base-card v-if="blockedUsers && blockedUsers.length">
|
||||
<os-card v-if="blockedUsers && blockedUsers.length">
|
||||
<ds-table :data="blockedUsers" :fields="fields" condensed>
|
||||
<template #avatar="scope">
|
||||
<nuxt-link
|
||||
@ -67,8 +67,8 @@
|
||||
</os-button>
|
||||
</template>
|
||||
</ds-table>
|
||||
</base-card>
|
||||
<base-card v-else>
|
||||
</os-card>
|
||||
<os-card v-else>
|
||||
<ds-space>
|
||||
<ds-placeholder>
|
||||
{{ $t('settings.blocked-users.empty') }}
|
||||
@ -79,12 +79,12 @@
|
||||
{{ $t('settings.blocked-users.how-to') }}
|
||||
</ds-text>
|
||||
</ds-space>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { blockedUsers, unblockUser } from '~/graphql/settings/BlockedUsers'
|
||||
import ProfileAvatar from '~/components/_new/generic/ProfileAvatar/ProfileAvatar'
|
||||
@ -94,6 +94,7 @@ export default {
|
||||
mixins: [scrollToContent],
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
ProfileAvatar,
|
||||
},
|
||||
|
||||
@ -26,7 +26,7 @@ describe('data-download.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('settings.download.name') }}</h2>
|
||||
<os-button
|
||||
variant="primary"
|
||||
@ -14,15 +14,15 @@
|
||||
<ds-space margin="large" />
|
||||
<ds-text>{{ $t('settings.download.description') }}</ds-text>
|
||||
<ds-space margin="large" />
|
||||
<base-card v-for="image in imageList" :key="image.key">
|
||||
<os-card v-for="image in imageList" :key="image.key">
|
||||
<a :href="image.url" target="_blank" rel="noopener noreferrer">{{ image.title }}</a>
|
||||
<ds-space margin="xxx-small" />
|
||||
</base-card>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { userDataQuery } from '~/graphql/User'
|
||||
@ -33,6 +33,7 @@ export default {
|
||||
mixins: [scrollToContent],
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
},
|
||||
created() {
|
||||
|
||||
@ -36,7 +36,7 @@ describe('delete-account.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -36,7 +36,7 @@ describe('embeds.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('settings.embeds.name') }}</h2>
|
||||
<ds-section>
|
||||
<ds-text>
|
||||
@ -51,18 +51,18 @@
|
||||
</ul>
|
||||
</ds-space>
|
||||
</ds-section>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard } from '@ocelot-social/ui'
|
||||
import axios from 'axios'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { updateUserMutation } from '~/graphql/User.js'
|
||||
import scrollToContent from './scroll-to-content.js'
|
||||
|
||||
export default {
|
||||
components: { OsButton },
|
||||
components: { OsButton, OsCard },
|
||||
mixins: [scrollToContent],
|
||||
head() {
|
||||
return {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<ds-form class="settings-form" v-model="formData" :schema="formSchema" @submit="submit">
|
||||
<template #default="{ errors }">
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('settings.data.name') }}</h2>
|
||||
<ds-input
|
||||
id="name"
|
||||
@ -39,13 +39,13 @@
|
||||
<template #icon><os-icon :icon="icons.check" /></template>
|
||||
{{ $t('actions.save') }}
|
||||
</os-button>
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
</ds-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
||||
import { OsButton, OsCard, OsIcon } from '@ocelot-social/ui'
|
||||
import { iconRegistry } from '~/utils/iconRegistry'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import UniqueSlugForm from '~/components/utils/UniqueSlugForm'
|
||||
@ -58,6 +58,7 @@ export default {
|
||||
name: 'Settings',
|
||||
components: {
|
||||
OsButton,
|
||||
OsCard,
|
||||
OsIcon,
|
||||
LocationSelect,
|
||||
},
|
||||
|
||||
@ -26,7 +26,7 @@ describe('invites.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.classes('base-card')).toBe(true)
|
||||
expect(wrapper.classes('os-card')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<os-card>
|
||||
<h2 class="title">{{ $t('settings.invites.name') }}</h2>
|
||||
<hc-empty icon="tasks" message="Coming Soon…" />
|
||||
</base-card>
|
||||
</os-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { OsCard } from '@ocelot-social/ui'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
import scrollToContent from './scroll-to-content.js'
|
||||
|
||||
export default {
|
||||
mixins: [scrollToContent],
|
||||
components: {
|
||||
OsCard,
|
||||
HcEmpty,
|
||||
},
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user