Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into release-12272023
Browse files Browse the repository at this point in the history
This merge includes the latest updates and bug fixes from the main branch into the release branch for the upcoming release dated 12/27/2023.
  • Loading branch information
KukretiShubham committed Dec 27, 2023
2 parents dd51e75 + 76515f8 commit 76170c4
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 60 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"flushDb": "node ./scripts/flushDb.mjs",
"upgradeDb": "node ./scripts/upgrade.mjs",
"genApiPaths": "node ./scripts/generate-built-in-api-paths.mjs",
"copy": "node ./scripts/copy.mjs"
"copy": "node ./scripts/copy.mjs",
"migratePosts": "node ./scripts/upgrade-posts-v2.mjs"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.4",
Expand Down Expand Up @@ -65,7 +66,7 @@
"@crossmint/client-sdk-base": "^1.0.1-alpha.6",
"@crossmint/client-sdk-react-ui": "^1.0.1-alpha.6",
"@devprotocol/clubs-core": "3.0.0-alpha.0",
"@devprotocol/clubs-plugin-posts": "0.8.3",
"@devprotocol/clubs-plugin-posts": "0.8.6",
"@devprotocol/dev-kit": "8.6.0",
"@devprotocol/elements": "1.1.0",
"@devprotocol/hashi": "2.2.2",
Expand Down
201 changes: 201 additions & 0 deletions scripts/upgrade-posts-v2.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { createClient } from 'redis'
import dotenv from 'dotenv'
import { decode, encode } from '@devprotocol/clubs-core'
import { v5 as uuidv5 } from 'uuid'
import { toUtf8Bytes } from 'ethers'

dotenv.config()

let isIndexCreated = false

const upgradeConfig = (decodedConfig, feeds) => {
const upgradedConfig = {
...decodedConfig,
plugins: decodedConfig.plugins.map((plugin) => {
/**
* Find the posts plugin
*/
if (plugin.id === 'devprotocol:clubs:plugin:posts') {
/**
* Find the feeds option and replace it with the new one
*/
const options = plugin.options.map((option) => {
if (option.key === 'feeds') {
return {
key: 'feeds',
value: feeds,
}
}
return option
})

return { ...plugin, options }
}
return plugin
}),
}

return encode(upgradedConfig)
}

const main = async () => {
try {
const client = createClient({
url: process.env.REDIS_URL,
username: process.env.REDIS_USERNAME ?? '',
password: process.env.REDIS_PASSWORD ?? '',
})
await client.connect()

/**
* Drop the indexes
*/
await Promise.all([
client.ft.dropindex('idx::devprotocol:clubs:plugin:posts::post'),
client.ft.dropindex('idx::devprotocol:clubs:plugin:posts::comment'),
client.ft.dropindex('idx::devprotocol:clubs:plugin:posts::reaction'),
client.ft.dropindex('idx::devprotocol:clubs:plugin:posts::option'),
])

/**
* Loop through the redis keys
*/
for await (const key of client.scanIterator()) {
if (key.includes(':')) {
// This is not a ClubsConfiguration
continue
}

/**
* Fetch the encoded config associated with the key
*/

const encodedConfig = await client.get(key)
const decodedConfig = decode(encodedConfig)

/**
* Find the posts plugin
*/
const pluginPost = decodedConfig.plugins.find(
(plugin) => plugin.id === 'devprotocol:clubs:plugin:posts',
)

/** Club doesn't have Posts installed, continue */
if (!pluginPost) {
console.log('Skipped: no post plugin', key)
continue
}

/**
* Find the feeds option
**/
const feeds = pluginPost.options.find((option) => option.key === 'feeds')

/** Club doesn't have Posts installed, continue */
if (!feeds) {
console.log('Skipped: no feeds found', key)
continue
}

/**
* We add the new feed value for copying the posts content
*/
const scope = uuidv5(
toUtf8Bytes('default-2'),
uuidv5(decodedConfig.url, uuidv5.URL),
)
const appendedFeeds = [
...feeds.value.filter((feed) => feed.database.key !== scope),
{
id: 'default-2',
slug: 'posts',
database: {
type: 'documents:redis',
key: scope,
},
},
]

/**
* Create a new config
*/
const addedFeedValueConfig = upgradeConfig(decodedConfig, appendedFeeds)

/**
* Save the upgraded config
*/
await client.set(key, addedFeedValueConfig)
console.log('Upgraded', key)

/**
* Create required indexes
* This API can be called repeatedly, but it has no effect after the first call, so call it only once.
*/
if (isIndexCreated === false) {
const res1 = await fetch(
`http://localhost:3000/sites_/${key}/api/devprotocol:clubs:plugin:posts/indexing/documents:redis`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
)

if (!res1.ok) {
console.log('status is: ', res1.status)
console.log('status text is: ', res1.statusText)
console.log('Failed to create indexes', key)
console.log('----')
continue
}
isIndexCreated = true
}

/**
* Copy posts content
*/
const oldId = 'default'
const newId = 'default-2'
const copyUrl = `http://localhost:3000/sites_/${key}/api/devprotocol:clubs:plugin:posts/${oldId}/copy/to/${newId}`
console.log('Copying posts content', key, copyUrl)

const res2 = await fetch(copyUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
})

if (!res2.ok) {
console.log('status is: ', res2.status)
console.log('status text is: ', res2.statusText)
console.log('Failed to copy posts content', key)
console.log('----')
continue
}

/**
* Remove the prior feed value
*/
const removedFeeds = appendedFeeds.map((feed) =>
feed.id === oldId ? { ...feed, slug: '_old_default_feed' } : feed,
)
const upgradedConfig = upgradeConfig(decodedConfig, removedFeeds)

/**
* Set the upgraded config
*/
await client.set(key, upgradedConfig)
console.log('Upgraded', key)
}

console.log('DB Upgraded')
await client.quit()
console.log('Closed the DB connection')
} catch (error) {
console.log(error)
}
}

main()
1 change: 1 addition & 0 deletions src/components/Collections/CollectionView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
}
const getSlotsForMembership = async (membership: CollectionMembership) => {
if (membership.memberCount === 0) return undefined
const provider = new JsonRpcProvider(rpcUrl)
let left = await callSlotCollections(provider, 'getSlotsLeft', [
propertyAddress,
Expand Down
28 changes: 18 additions & 10 deletions src/components/Domain/Domain.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<script lang="ts">
import HSButton from '@components/Primitives/Hashi/HSButton.vue'
import { renderSpotlight } from '@fixtures/ui/renderSpotLight'
import { Strings } from './i18n'
import { i18nFactory } from '@devprotocol/clubs-core'
const i18nBase = i18nFactory(Strings)
let i18n = i18nBase(['en'])
type Data = {
daoName: string
fetching?: boolean
valid?: boolean
i18n: ReturnType<typeof i18nBase>
}
let timer: NodeJS.Timeout
Expand All @@ -25,6 +31,7 @@ export default {
daoName: '',
fetching: undefined,
valid: undefined,
i18n: i18nBase(['en']),
}) as Data,
methods: {
async verifySiteName() {
Expand All @@ -48,6 +55,7 @@ export default {
this.daoName = this.namePreset
this.verifySiteName()
}
i18n = i18nBase(navigator.languages)
},
computed: {
network() {
Expand All @@ -66,9 +74,9 @@ export default {
<div class="relative grid justify-center p-4 md:p-0">
<section class="my-16 grid gap-8 text-center md:my-32">
<h1 class="text-2xl font-bold md:text-5xl">
It All Starts with a Domain
{{ i18n('Header') }}
</h1>
<p>You can use your preferred domain for your club.</p>
<p>{{ i18n('SubHeader') }}</p>
</section>

<div class="grid justify-center gap-16 md:gap-32">
Expand Down Expand Up @@ -110,12 +118,12 @@ export default {
v-if="fetching === false && typeof valid === 'boolean'"
class="absolute left-0 top-[100%] mt-2 rounded-md bg-white p-2 text-sm"
>
<span v-if="valid === true" class="text-[#30a83d]"
>Domain available</span
>
<span v-if="valid === false" class="text-error-400"
>Domain unavailable</span
>
<span v-if="valid === true" class="text-[#30a83d]">{{
i18n('DomainAvailable')
}}</span>
<span v-if="valid === false" class="text-error-400">{{
i18n('DomainUnavailable')
}}</span>
</p>
</div>
</section>
Expand All @@ -125,13 +133,13 @@ export default {
v-if="fetching === false && valid"
type="filled large fullwidth"
:link="`/connect/${daoName}`"
>Continue</HSButton
>{{ i18n('Continue') }}</HSButton
>
<HSButton
v-if="fetching || !valid"
type="filled large fullwidth"
isDisabled="true"
>Continue</HSButton
>{{ i18n('Continue') }}</HSButton
>
</section>
</div>
Expand Down
24 changes: 24 additions & 0 deletions src/components/Domain/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { ClubsI18nParts } from '@devprotocol/clubs-core'

export const Strings = {
Header: {
en: () => 'It All Starts with a Domain',
ja: () => 'ドメインから全ては始まります',
},
SubHeader: {
en: () => 'You can use your preferred domain for your club.',
ja: () => '好きなドメインをClubsで使用することができます',
},
DomainAvailable: {
en: () => 'Domain available',
ja: () => '利用可能なドメイン',
},
DomainUnavailable: {
en: () => 'Domain unavailable',
ja: () => '利用できないドメイン',
},
Continue: {
en: () => 'Continue',
ja: () => '続ける',
},
} satisfies ClubsI18nParts
18 changes: 14 additions & 4 deletions src/components/EmailConnect/EmailConnect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@
let emailErrorMessage = ''
let emailSent = false
let emailSending = false
import { Strings } from './i18n'
import { onMount } from 'svelte'
import { i18nFactory } from '@devprotocol/clubs-core'
const emailEndpoint = import.meta.env.PUBLIC_EMAIL_AUTH_ENDPOINT
const i18nBase = i18nFactory(Strings)
let i18n = i18nBase(['en'])
onMount(() => {
i18n = i18nBase(navigator.languages)
})
const sendMagicLink = async () => {
if (emailSent) {
return
Expand Down Expand Up @@ -45,12 +55,12 @@
{#if emailSending}
<span
class="hs-button is-filled animate-pulse rounded bg-gray-500/60 px-8 py-4 text-inherit"
>Sending a magic link</span
>{i18n('EmailSending')}</span
>
{:else if emailSent}
<span
class="hs-button is-filled bg-success-300 cursor-default px-8 py-4 text-inherit"
>Check your inbox</span
>{i18n('EmailSent')}</span
>
{:else}
<div class="grid auto-rows-auto grid-cols-[1fr_auto] items-center gap-2">
Expand All @@ -60,15 +70,15 @@
id="email"
name="email"
type="email"
placeholder="Your email"
placeholder={i18n('EmailPlaceholder')}
class="hs-form-field__input"
/>
</label>
<button
on:click|preventDefault={(_) => sendMagicLink()}
class="hs-button is-filled is-native-blue px-8 py-4 text-inherit"
>
Continue
{i18n('Continue')}
</button>
{#if emailErrorMessage.length > 0}
<span class="bg-danger-300 col-span-2 rounded-md px-8 py-4 text-sm"
Expand Down
Loading

0 comments on commit 76170c4

Please sign in to comment.