Compare commits
No commits in common. "c7cf1d21116ea110a4619f56973f224c8e773463" and "b06149cf220fe06042ca2acd0df720dacf1eb87c" have entirely different histories.
c7cf1d2111
...
b06149cf22
11 changed files with 55 additions and 117 deletions
|
@ -115,7 +115,7 @@ class OutfitsController < ApplicationController
|
||||||
|
|
||||||
def outfit_params
|
def outfit_params
|
||||||
params.require(:outfit).permit(
|
params.require(:outfit).permit(
|
||||||
:name, :starred, :alt_style_id, item_ids: {worn: [], closeted: []},
|
:name, :starred, item_ids: {worn: [], closeted: []},
|
||||||
biology: [:species_id, :color_id, :pose])
|
biology: [:species_id, :color_id, :pose])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
useToast,
|
useToast,
|
||||||
useToken,
|
useToken,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { ChevronDownIcon, WarningTwoIcon } from "@chakra-ui/icons";
|
import { ChevronDownIcon } from "@chakra-ui/icons";
|
||||||
import { loadable } from "../util";
|
import { loadable } from "../util";
|
||||||
|
|
||||||
import { petAppearanceFragment } from "../components/useOutfitAppearance";
|
import { petAppearanceFragment } from "../components/useOutfitAppearance";
|
||||||
|
@ -42,7 +42,6 @@ import twemojiSunglasses from "../images/twemoji/sunglasses.svg";
|
||||||
import twemojiQuestion from "../images/twemoji/question.svg";
|
import twemojiQuestion from "../images/twemoji/question.svg";
|
||||||
import twemojiMasc from "../images/twemoji/masc.svg";
|
import twemojiMasc from "../images/twemoji/masc.svg";
|
||||||
import twemojiFem from "../images/twemoji/fem.svg";
|
import twemojiFem from "../images/twemoji/fem.svg";
|
||||||
import twemojiHourglass from "../images/twemoji/hourglass.svg";
|
|
||||||
|
|
||||||
const PosePickerSupport = loadable(() => import("./support/PosePickerSupport"));
|
const PosePickerSupport = loadable(() => import("./support/PosePickerSupport"));
|
||||||
|
|
||||||
|
@ -219,11 +218,18 @@ function PosePicker({
|
||||||
gap="2"
|
gap="2"
|
||||||
index={tabIndex}
|
index={tabIndex}
|
||||||
onChange={setTabIndex}
|
onChange={setTabIndex}
|
||||||
|
// HACK: To only apply `initialFocusRef` to the selected input
|
||||||
|
// in the *active* tab, we just use `isLazy` to only *render*
|
||||||
|
// the active tab. We could also watch the tab state and set
|
||||||
|
// the ref accordingly!
|
||||||
|
isLazy
|
||||||
>
|
>
|
||||||
<TabList paddingX="2" paddingY="0">
|
<SupportOnly>
|
||||||
<Tab width="50%">Expressions</Tab>
|
<TabList paddingX="2" paddingY="0">
|
||||||
<Tab width="50%">Styles</Tab>
|
<Tab width="50%">Expressions</Tab>
|
||||||
</TabList>
|
<Tab width="50%">Styles</Tab>
|
||||||
|
</TabList>
|
||||||
|
</SupportOnly>
|
||||||
<TabPanels position="relative">
|
<TabPanels position="relative">
|
||||||
<TabPanel paddingX="4" paddingY="0">
|
<TabPanel paddingX="4" paddingY="0">
|
||||||
{isInSupportMode ? (
|
{isInSupportMode ? (
|
||||||
|
@ -232,9 +238,7 @@ function PosePicker({
|
||||||
colorId={colorId}
|
colorId={colorId}
|
||||||
pose={pose}
|
pose={pose}
|
||||||
appearanceId={appearanceId}
|
appearanceId={appearanceId}
|
||||||
initialFocusRef={
|
initialFocusRef={initialFocusRef}
|
||||||
tabIndex === 0 ? initialFocusRef : null
|
|
||||||
}
|
|
||||||
dispatchToOutfit={dispatchToOutfit}
|
dispatchToOutfit={dispatchToOutfit}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
@ -242,9 +246,7 @@ function PosePicker({
|
||||||
<PosePickerTable
|
<PosePickerTable
|
||||||
poseInfos={poseInfos}
|
poseInfos={poseInfos}
|
||||||
onChange={onChangePose}
|
onChange={onChangePose}
|
||||||
initialFocusRef={
|
initialFocusRef={initialFocusRef}
|
||||||
tabIndex === 0 ? initialFocusRef : null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
{numStandardPoses == 0 && (
|
{numStandardPoses == 0 && (
|
||||||
<PosePickerEmptyExplanation />
|
<PosePickerEmptyExplanation />
|
||||||
|
@ -265,7 +267,7 @@ function PosePicker({
|
||||||
selectedStyleId={altStyleId}
|
selectedStyleId={altStyleId}
|
||||||
altStyles={altStyles}
|
altStyles={altStyles}
|
||||||
onChange={onChangeStyle}
|
onChange={onChangeStyle}
|
||||||
initialFocusRef={tabIndex === 1 ? initialFocusRef : null}
|
initialFocusRef={initialFocusRef}
|
||||||
/>
|
/>
|
||||||
<StyleExplanation />
|
<StyleExplanation />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
@ -422,22 +424,14 @@ function PosePickerTable({ poseInfos, onChange, initialFocusRef }) {
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{poseInfos.unconverted.isAvailable && (
|
{poseInfos.unconverted.isAvailable && (
|
||||||
<Flex
|
<PoseOption
|
||||||
align="center"
|
poseInfo={poseInfos.unconverted}
|
||||||
justify="center"
|
onChange={onChange}
|
||||||
gap="1"
|
inputRef={poseInfos.unconverted.isSelected && initialFocusRef}
|
||||||
|
size="sm"
|
||||||
|
label="Unconverted"
|
||||||
marginTop="2"
|
marginTop="2"
|
||||||
marginBottom="2"
|
/>
|
||||||
>
|
|
||||||
<PoseOption
|
|
||||||
poseInfo={poseInfos.unconverted}
|
|
||||||
onChange={onChange}
|
|
||||||
inputRef={poseInfos.unconverted.isSelected && initialFocusRef}
|
|
||||||
size="sm"
|
|
||||||
label="Retired UC"
|
|
||||||
/>
|
|
||||||
<RetiredUCWarning isSelected={poseInfos.unconverted.isSelected} />
|
|
||||||
</Flex>
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -630,40 +624,6 @@ function PosePickerEmptyExplanation() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function RetiredUCWarning({ isSelected }) {
|
|
||||||
return (
|
|
||||||
<Popover placement="right" trigger="hover">
|
|
||||||
<PopoverTrigger>
|
|
||||||
<Box
|
|
||||||
as="button"
|
|
||||||
tabIndex="0"
|
|
||||||
aria-label="Warning"
|
|
||||||
cursor="help"
|
|
||||||
lineHeight="1"
|
|
||||||
opacity={isSelected ? "1" : "0.75"}
|
|
||||||
transform={isSelected ? "scale(1)" : "scale(0.8)"}
|
|
||||||
color={isSelected ? "yellow.500" : "inherit"}
|
|
||||||
transition="all 0.2s"
|
|
||||||
padding="1"
|
|
||||||
>
|
|
||||||
<WarningTwoIcon />
|
|
||||||
</Box>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent
|
|
||||||
background="blackAlpha.800"
|
|
||||||
borderColor="blackAlpha.900"
|
|
||||||
color="white"
|
|
||||||
padding="2"
|
|
||||||
fontSize="sm"
|
|
||||||
>
|
|
||||||
"Unconverted" pets are no longer available on Neopets.com, and have been
|
|
||||||
replaced with the very similar Styles feature. We're just keeping this
|
|
||||||
as an archive!
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function StyleSelect({
|
function StyleSelect({
|
||||||
selectedStyleId,
|
selectedStyleId,
|
||||||
altStyles,
|
altStyles,
|
||||||
|
@ -788,6 +748,10 @@ function StyleExplanation() {
|
||||||
Styling Chamber
|
Styling Chamber
|
||||||
</Box>
|
</Box>
|
||||||
. Not all items fit Alt Style pets. The pet's color doesn't have to match.
|
. Not all items fit Alt Style pets. The pet's color doesn't have to match.
|
||||||
|
<SupportOnly>
|
||||||
|
<br />
|
||||||
|
WIP: Only Support staff see this tab for now! 💖
|
||||||
|
</SupportOnly>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -925,7 +889,7 @@ function getIcon(pose) {
|
||||||
} else if (["SICK_MASC", "SICK_FEM"].includes(pose)) {
|
} else if (["SICK_MASC", "SICK_FEM"].includes(pose)) {
|
||||||
return twemojiSick;
|
return twemojiSick;
|
||||||
} else if (pose === "UNCONVERTED") {
|
} else if (pose === "UNCONVERTED") {
|
||||||
return twemojiHourglass;
|
return twemojiSunglasses;
|
||||||
} else {
|
} else {
|
||||||
return twemojiSmile;
|
return twemojiSmile;
|
||||||
}
|
}
|
||||||
|
@ -939,7 +903,7 @@ function getLabel(pose) {
|
||||||
} else if (pose === "SICK_MASC" || pose === "SICK_FEM") {
|
} else if (pose === "SICK_MASC" || pose === "SICK_FEM") {
|
||||||
return "Sick";
|
return "Sick";
|
||||||
} else if (pose === "UNCONVERTED") {
|
} else if (pose === "UNCONVERTED") {
|
||||||
return "Retired UC";
|
return "Classic UC";
|
||||||
} else {
|
} else {
|
||||||
return "Default";
|
return "Default";
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,6 @@ function useOutfitSaving(outfitState, dispatchToOutfit) {
|
||||||
speciesId: outfitState.speciesId,
|
speciesId: outfitState.speciesId,
|
||||||
colorId: outfitState.colorId,
|
colorId: outfitState.colorId,
|
||||||
pose: outfitState.pose,
|
pose: outfitState.pose,
|
||||||
altStyleId: outfitState.altStyleId,
|
|
||||||
wornItemIds: [...outfitState.wornItemIds],
|
wornItemIds: [...outfitState.wornItemIds],
|
||||||
closetedItemIds: [...outfitState.closetedItemIds],
|
closetedItemIds: [...outfitState.closetedItemIds],
|
||||||
})
|
})
|
||||||
|
|
|
@ -447,7 +447,6 @@ function getOutfitStateFromOutfitData(outfit) {
|
||||||
speciesId: outfit.speciesId,
|
speciesId: outfit.speciesId,
|
||||||
colorId: outfit.colorId,
|
colorId: outfit.colorId,
|
||||||
pose: outfit.pose,
|
pose: outfit.pose,
|
||||||
altStyleId: outfit.altStyleId,
|
|
||||||
wornItemIds: new Set(outfit.wornItemIds),
|
wornItemIds: new Set(outfit.wornItemIds),
|
||||||
closetedItemIds: new Set(outfit.closetedItemIds),
|
closetedItemIds: new Set(outfit.closetedItemIds),
|
||||||
};
|
};
|
||||||
|
@ -704,6 +703,12 @@ function buildOutfitQueryString(outfitState) {
|
||||||
color: colorId || "",
|
color: colorId || "",
|
||||||
pose: pose || "",
|
pose: pose || "",
|
||||||
});
|
});
|
||||||
|
for (const itemId of wornItemIds) {
|
||||||
|
params.append("objects[]", itemId);
|
||||||
|
}
|
||||||
|
for (const itemId of closetedItemIds) {
|
||||||
|
params.append("closet[]", itemId);
|
||||||
|
}
|
||||||
if (altStyleId != null) {
|
if (altStyleId != null) {
|
||||||
params.append("style", altStyleId);
|
params.append("style", altStyleId);
|
||||||
}
|
}
|
||||||
|
@ -712,12 +717,6 @@ function buildOutfitQueryString(outfitState) {
|
||||||
// refers to "PetState", the database table name for pet appearances.
|
// refers to "PetState", the database table name for pet appearances.
|
||||||
params.append("state", appearanceId);
|
params.append("state", appearanceId);
|
||||||
}
|
}
|
||||||
for (const itemId of wornItemIds) {
|
|
||||||
params.append("objects[]", itemId);
|
|
||||||
}
|
|
||||||
for (const itemId of closetedItemIds) {
|
|
||||||
params.append("closet[]", itemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return params.toString();
|
return params.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#FFE8B6" d="M21 18c0-2.001 3.246-3.369 5-6 2-3 2-10 2-10H8s0 7 2 10c1.754 2.631 5 3.999 5 6s-3.246 3.369-5 6c-2 3-2 10-2 10h20s0-7-2-10c-1.754-2.631-5-3.999-5-6z"/><path fill="#FFAC33" d="M20.999 24c-.999 0-2.057-1-2.057-2C19 20.287 19 19.154 19 18c0-3.22 3.034-4.561 4.9-7H12.1c1.865 2.439 4.9 3.78 4.9 7 0 1.155 0 2.289.058 4 0 1-1.058 2-2.058 2-2 0-3.595 1.784-4 3-1 3-1 7-1 7h16s0-4-1-7c-.405-1.216-2.001-3-4.001-3z"/><path fill="#3B88C3" d="M30 34c0 1.104-.896 2-2 2H8c-1.104 0-2-.896-2-2s.896-2 2-2h20c1.104 0 2 .896 2 2zm0-32c0 1.104-.896 2-2 2H8c-1.104 0-2-.896-2-2s.896-2 2-2h20c1.104 0 2 .896 2 2z"/></svg>
|
|
Before Width: | Height: | Size: 688 B |
|
@ -30,9 +30,7 @@ export function useDeleteOutfitMutation(options = {}) {
|
||||||
...options,
|
...options,
|
||||||
mutationFn: deleteOutfit,
|
mutationFn: deleteOutfit,
|
||||||
onSuccess: (emptyData, id, context) => {
|
onSuccess: (emptyData, id, context) => {
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({ queryKey: ["outfits", String(id)] });
|
||||||
queryKey: ["outfits", String(id)],
|
|
||||||
});
|
|
||||||
if (options.onSuccess) {
|
if (options.onSuccess) {
|
||||||
options.onSuccess(emptyData, id, context);
|
options.onSuccess(emptyData, id, context);
|
||||||
}
|
}
|
||||||
|
@ -44,9 +42,7 @@ async function loadSavedOutfit(id) {
|
||||||
const res = await fetch(`/outfits/${encodeURIComponent(id)}.json`);
|
const res = await fetch(`/outfits/${encodeURIComponent(id)}.json`);
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(
|
throw new Error(`loading outfit failed: ${res.status} ${res.statusText}`);
|
||||||
`loading outfit failed: ${res.status} ${res.statusText}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json().then(normalizeOutfit);
|
return res.json().then(normalizeOutfit);
|
||||||
|
@ -58,7 +54,6 @@ async function saveOutfit({
|
||||||
speciesId,
|
speciesId,
|
||||||
colorId,
|
colorId,
|
||||||
pose,
|
pose,
|
||||||
altStyleId,
|
|
||||||
wornItemIds,
|
wornItemIds,
|
||||||
closetedItemIds,
|
closetedItemIds,
|
||||||
}) {
|
}) {
|
||||||
|
@ -70,7 +65,6 @@ async function saveOutfit({
|
||||||
color_id: colorId,
|
color_id: colorId,
|
||||||
pose: pose,
|
pose: pose,
|
||||||
},
|
},
|
||||||
alt_style_id: altStyleId,
|
|
||||||
item_ids: { worn: wornItemIds, closeted: closetedItemIds },
|
item_ids: { worn: wornItemIds, closeted: closetedItemIds },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -97,9 +91,7 @@ async function saveOutfit({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(
|
throw new Error(`saving outfit failed: ${res.status} ${res.statusText}`);
|
||||||
`saving outfit failed: ${res.status} ${res.statusText}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json().then(normalizeOutfit);
|
return res.json().then(normalizeOutfit);
|
||||||
|
@ -114,9 +106,7 @@ async function deleteOutfit(id) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(
|
throw new Error(`deleting outfit failed: ${res.status} ${res.statusText}`);
|
||||||
`deleting outfit failed: ${res.status} ${res.statusText}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,11 +117,8 @@ function normalizeOutfit(outfit) {
|
||||||
speciesId: String(outfit.species_id),
|
speciesId: String(outfit.species_id),
|
||||||
colorId: String(outfit.color_id),
|
colorId: String(outfit.color_id),
|
||||||
pose: outfit.pose,
|
pose: outfit.pose,
|
||||||
altStyleId: outfit.alt_style_id ? String(outfit.alt_style_id) : null,
|
|
||||||
wornItemIds: (outfit.item_ids?.worn || []).map((id) => String(id)),
|
wornItemIds: (outfit.item_ids?.worn || []).map((id) => String(id)),
|
||||||
closetedItemIds: (outfit.item_ids?.closeted || []).map((id) =>
|
closetedItemIds: (outfit.item_ids?.closeted || []).map((id) => String(id)),
|
||||||
String(id),
|
|
||||||
),
|
|
||||||
creator: outfit.user ? { id: String(outfit.user.id) } : null,
|
creator: outfit.user ? { id: String(outfit.user.id) } : null,
|
||||||
createdAt: outfit.created_at,
|
createdAt: outfit.created_at,
|
||||||
updatedAt: outfit.updated_at,
|
updatedAt: outfit.updated_at,
|
||||||
|
|
|
@ -4,7 +4,6 @@ class Outfit < ApplicationRecord
|
||||||
class_name: 'ItemOutfitRelationship'
|
class_name: 'ItemOutfitRelationship'
|
||||||
has_many :worn_items, through: :worn_item_outfit_relationships, source: :item
|
has_many :worn_items, through: :worn_item_outfit_relationships, source: :item
|
||||||
|
|
||||||
belongs_to :alt_style, optional: true
|
|
||||||
belongs_to :pet_state, optional: true # We validate presence below!
|
belongs_to :pet_state, optional: true # We validate presence below!
|
||||||
belongs_to :user, optional: true
|
belongs_to :user, optional: true
|
||||||
|
|
||||||
|
@ -83,8 +82,7 @@ class Outfit < ApplicationRecord
|
||||||
|
|
||||||
def as_json(more_options={})
|
def as_json(more_options={})
|
||||||
serializable_hash(
|
serializable_hash(
|
||||||
only: [:id, :name, :pet_state_id, :starred, :created_at, :updated_at,
|
only: [:id, :name, :pet_state_id, :starred, :created_at, :updated_at],
|
||||||
:alt_style_id],
|
|
||||||
methods: [:color_id, :species_id, :pose, :item_ids, :user]
|
methods: [:color_id, :species_id, :pose, :item_ids, :user]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
- title "Styling Studio"
|
- title "Styling Studio"
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Here's all the new NC Pet Styles we have! They're available in the app too,
|
We're getting set up with the new NC Pet Styles! They're not ready in the app
|
||||||
by opening the emotion picker and clicking the "Styles" tab.
|
yet, but here's what we have so far!
|
||||||
|
|
||||||
%p
|
%p
|
||||||
If you have an Alt Style we don't, please model it by entering your pet's
|
If you have one we don't, please model it by entering your pet's name on the
|
||||||
name on the homepage! Thank you! 💖
|
homepage! Thank you! 💖
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Also, heads-up: Style tokens are pretty different from normal wearables, so
|
Also, heads-up: Style tokens are pretty different from normal wearables, so
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
= advertise_campaign_progress @campaign
|
= advertise_campaign_progress @campaign
|
||||||
|
|
||||||
.notice
|
.notice
|
||||||
%strong Alt styles are ready now!
|
%strong Happy NC UC day!
|
||||||
You can find them by opening the emotion picker, then clicking "Styles".
|
We're working on Styling Studio support,
|
||||||
|
= link_to("here's what we have so far", alt_styles_path) + "!"
|
||||||
%br
|
%br
|
||||||
= link_to("Here's our reference page, too!", alt_styles_path)
|
Thank you for helping us model the new styles, we appreciate it lots!!! 💖
|
||||||
Thanks again for all your help, let us know how it works for you! 💖
|
|
||||||
|
|
||||||
%p#pet-not-found.alert= t 'pets.load.not_found'
|
%p#pet-not-found.alert= t 'pets.load.not_found'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
class AddAltStyleIdToOutfits < ActiveRecord::Migration[7.1]
|
|
||||||
def change
|
|
||||||
add_reference :outfits, :alt_style, null: true, foreign_key: true
|
|
||||||
end
|
|
||||||
end
|
|
15
db/schema.rb
15
db/schema.rb
|
@ -10,13 +10,13 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.1].define(version: 2024_02_01_134440) do
|
ActiveRecord::Schema[7.1].define(version: 2024_01_29_114639) do
|
||||||
create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
|
create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_general_ci", force: :cascade do |t|
|
||||||
t.integer "species_id", null: false
|
t.integer "species_id", null: false
|
||||||
t.integer "color_id", null: false
|
t.integer "color_id", null: false
|
||||||
t.integer "body_id", null: false
|
t.integer "body_id", null: false
|
||||||
t.datetime "created_at", precision: nil, null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["color_id"], name: "index_alt_styles_on_color_id"
|
t.index ["color_id"], name: "index_alt_styles_on_color_id"
|
||||||
t.index ["species_id"], name: "index_alt_styles_on_species_id"
|
t.index ["species_id"], name: "index_alt_styles_on_species_id"
|
||||||
end
|
end
|
||||||
|
@ -125,11 +125,11 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_01_134440) do
|
||||||
t.index ["outfit_id", "is_worn"], name: "index_item_outfit_relationships_on_outfit_id_and_is_worn"
|
t.index ["outfit_id", "is_worn"], name: "index_item_outfit_relationships_on_outfit_id_and_is_worn"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "item_translations", id: :integer, charset: "latin1", collation: "latin1_swedish_ci", force: :cascade do |t|
|
create_table "item_translations", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
|
||||||
t.integer "item_id"
|
t.integer "item_id"
|
||||||
t.string "locale"
|
t.string "locale"
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.text "description"
|
t.text "description", size: :medium
|
||||||
t.string "rarity"
|
t.string "rarity"
|
||||||
t.datetime "created_at", precision: nil
|
t.datetime "created_at", precision: nil
|
||||||
t.datetime "updated_at", precision: nil
|
t.datetime "updated_at", precision: nil
|
||||||
|
@ -191,8 +191,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_01_134440) do
|
||||||
t.string "image"
|
t.string "image"
|
||||||
t.string "image_layers_hash"
|
t.string "image_layers_hash"
|
||||||
t.boolean "image_enqueued", default: false, null: false
|
t.boolean "image_enqueued", default: false, null: false
|
||||||
t.bigint "alt_style_id"
|
|
||||||
t.index ["alt_style_id"], name: "index_outfits_on_alt_style_id"
|
|
||||||
t.index ["pet_state_id"], name: "index_outfits_on_pet_state_id"
|
t.index ["pet_state_id"], name: "index_outfits_on_pet_state_id"
|
||||||
t.index ["user_id"], name: "index_outfits_on_user_id"
|
t.index ["user_id"], name: "index_outfits_on_user_id"
|
||||||
end
|
end
|
||||||
|
@ -316,5 +314,4 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_01_134440) do
|
||||||
|
|
||||||
add_foreign_key "alt_styles", "colors"
|
add_foreign_key "alt_styles", "colors"
|
||||||
add_foreign_key "alt_styles", "species"
|
add_foreign_key "alt_styles", "species"
|
||||||
add_foreign_key "outfits", "alt_styles"
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue